about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPierre LALET <pierre.lalet@cea.fr>2019-02-27 20:29:44 +0100
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2019-03-05 16:52:51 +0100
commitd3a42fa5dcdb0c467586eb6b92271fa4dbeb648b (patch)
treeb5ca14f60ad2a10148990ffc30e4bad8f49c9283
parent944806c506446c918eb74c17a605f5f56d4b75e0 (diff)
downloadmiasm-d3a42fa5dcdb0c467586eb6b92271fa4dbeb648b.tar.gz
miasm-d3a42fa5dcdb0c467586eb6b92271fa4dbeb648b.zip
Include elfesteem fork in miasm
-rw-r--r--.codespell_ignore1
-rw-r--r--README.md13
-rwxr-xr-xexample/asm/shellcode.py4
-rw-r--r--example/elfesteem/minidump_to_pe.py48
-rw-r--r--example/elfesteem/test_pe.py31
-rwxr-xr-xexample/jitter/arm_sc.py2
-rw-r--r--example/jitter/run_with_linuxenv.py2
-rw-r--r--example/jitter/unpack_upx.py2
-rw-r--r--miasm/analysis/binary.py4
-rw-r--r--miasm/elfesteem/__init__.py3
-rw-r--r--miasm/elfesteem/cstruct.py154
-rw-r--r--miasm/elfesteem/elf.py1538
-rw-r--r--miasm/elfesteem/elf_init.py878
-rw-r--r--miasm/elfesteem/minidump.py545
-rw-r--r--miasm/elfesteem/minidump_init.py194
-rw-r--r--miasm/elfesteem/new_cstruct.py265
-rw-r--r--miasm/elfesteem/pe.py1668
-rw-r--r--miasm/elfesteem/pe_init.py603
-rw-r--r--miasm/elfesteem/strpatchwork.py106
-rw-r--r--miasm/jitter/loader/elf.py12
-rw-r--r--miasm/jitter/loader/pe.py6
-rw-r--r--miasm/os_dep/win_api_x86_32_seh.py2
-rw-r--r--requirements.txt1
-rwxr-xr-xsetup.py1
-rw-r--r--test/analysis/dse.py2
-rw-r--r--test/arch/aarch64/unit/asm_test.py2
-rw-r--r--test/arch/mips32/unit/asm_test.py2
-rw-r--r--test/arch/x86/unit/asm_test.py2
28 files changed, 6058 insertions, 33 deletions
diff --git a/.codespell_ignore b/.codespell_ignore
index 3724a1f4..8eab9f6f 100644
--- a/.codespell_ignore
+++ b/.codespell_ignore
@@ -4,3 +4,4 @@ uint
 mye
 iff
 nto
+rela
diff --git a/README.md b/README.md
index 010f75d6..0d1fdf8a 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ Miasm is a free and open source (GPLv2) reverse engineering framework.
 Miasm aims to analyze / modify / generate binary programs. Here is
 a non exhaustive list of features:
 
-* Opening / modifying / generating PE / ELF 32 / 64 LE / BE using Elfesteem
+* Opening / modifying / generating PE / ELF 32 / 64 LE / BE
 * Assembling / Disassembling X86 / ARM / MIPS / SH4 / MSP430
 * Representing assembly semantic using intermediate language
 * Emulating using JIT (dynamic code analysis, unpacking, ...)
@@ -525,7 +525,6 @@ Miasm uses:
 
 * python-pyparsing
 * python-dev
-* elfesteem from [Elfesteem](https://github.com/serpilliere/elfesteem.git)
 * optionally python-pycparser (version >= 2.17)
 
 To enable code JIT, one of the following module is mandatory:
@@ -539,14 +538,6 @@ To enable code JIT, one of the following module is mandatory:
 Configuration
 -------------
 
-* Install elfesteem
-```pycon
-git clone https://github.com/serpilliere/elfesteem.git elfesteem
-cd elfesteem
-python setup.py build
-sudo python setup.py install
-```
-
 To use the jitter, GCC or LLVM is recommended
 * GCC (any version)
 * Clang (any version)
@@ -570,7 +561,7 @@ Windows & IDA
 
 Most of Miasm's IDA plugins use a subset of Miasm functionality.
 A quick way to have them working is to add:
-* `elfesteem` directory and `pyparsing.py` to `C:\...\IDA\python\` or `pip install pyparsing elfesteem`
+* `pyparsing.py` to `C:\...\IDA\python\` or `pip install pyparsing`
 * `miasm/miasm` directory to `C:\...\IDA\python\`
 
 All features excepting JITter related ones will be available. For a more complete installation, please refer to above paragraphs.
diff --git a/example/asm/shellcode.py b/example/asm/shellcode.py
index ed489bbd..59ea3a94 100755
--- a/example/asm/shellcode.py
+++ b/example/asm/shellcode.py
@@ -4,8 +4,8 @@ from argparse import ArgumentParser
 from pdb import pm
 
 from future.utils import viewitems
-from elfesteem import pe_init
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem import pe_init
+from miasm.elfesteem.strpatchwork import StrPatchwork
 
 from miasm.core import parse_asm, asmblock
 from miasm.analysis.machine import Machine
diff --git a/example/elfesteem/minidump_to_pe.py b/example/elfesteem/minidump_to_pe.py
new file mode 100644
index 00000000..8aff3e62
--- /dev/null
+++ b/example/elfesteem/minidump_to_pe.py
@@ -0,0 +1,48 @@
+#! /usr/bin/env python
+"""Minidump to PE example"""
+
+import sys
+
+from future.utils import viewvalues
+
+from miasm.elfesteem.minidump_init import Minidump
+from miasm.elfesteem.pe_init import PE
+
+minidump = Minidump(open(sys.argv[1], 'rb').read())
+
+pe = PE()
+for i, memory in enumerate(sorted(viewvalues(minidump.memory),
+                                  key=lambda x:x.address)):
+    # Get section name
+    name = str(memory.name)
+    if not name:
+        name = "s_%02d" % i
+    else:
+        name = name.split('\\')[-1]
+
+    # Get section protection
+    protect = memory.pretty_protect
+    protect_mask = 0x20
+    if protect == "UNKNOWN":
+        protect_mask |= 0xe0000000
+    else:
+        if "EXECUTE" in protect:
+            protect_mask |= 1 << 29
+        if "READ" in protect:
+            protect_mask |= 1 << 30
+        if "WRITE" in protect:
+            protect_mask |= 1 << 31
+
+    # Add the section
+    pe.SHList.add_section(name=name, addr=memory.address, rawsize=memory.size,
+                          data=memory.content, flags=protect_mask)
+
+# Find entry point
+try:
+    entry_point = minidump.threads.Threads[0].ThreadContext.Eip[0]
+except AttributeError:
+    entry_point = minidump.threads.Threads[0].ThreadContext.Rip[0]
+
+pe.Opthdr.AddressOfEntryPoint = entry_point
+
+open("out_pe.bin", "wb").write(bytes(pe))
diff --git a/example/elfesteem/test_pe.py b/example/elfesteem/test_pe.py
new file mode 100644
index 00000000..e9cff0b4
--- /dev/null
+++ b/example/elfesteem/test_pe.py
@@ -0,0 +1,31 @@
+#! /usr/bin/env python
+
+import miasm.elfesteem.pe as pe
+from miasm.elfesteem.pe_init import PE
+import rlcompleter
+import readline
+import pdb
+import sys
+from pprint import pprint as pp
+readline.parse_and_bind("tab: complete")
+
+
+e_ = PE()
+mysh = b"\xc3"
+s_text = e_.SHList.add_section(
+    name="text", addr=0x1000, rawsize=0x1000, data=mysh)
+e_.Opthdr.AddressOfEntryPoint = s_text.addr
+new_dll = [({"name": "kernel32.dll",
+             "firstthunk": s_text.addr + 0x100},
+            ["CreateFileA", "SetFilePointer", "WriteFile", "CloseHandle"]
+            ),
+           ({"name": "USER32.dll",
+             "firstthunk": None},
+            ["SetDlgItemInt", "GetMenu", "HideCaret"]
+            )
+           ]
+e_.DirImport.add_dlldesc(new_dll)
+
+s_myimp = e_.SHList.add_section(name="myimp", rawsize=0x1000)
+e_.DirImport.set_rva(s_myimp.addr)
+open('uu.bin', 'wb').write(bytes(e_))
diff --git a/example/jitter/arm_sc.py b/example/jitter/arm_sc.py
index 8d5b5677..ddadbf29 100755
--- a/example/jitter/arm_sc.py
+++ b/example/jitter/arm_sc.py
@@ -3,7 +3,7 @@
 from miasm.core.utils import int_to_byte
 from miasm.analysis.sandbox import Sandbox_Linux_armb_str
 from miasm.analysis.sandbox import Sandbox_Linux_arml_str
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem.strpatchwork import StrPatchwork
 
 from pdb import pm
 
diff --git a/example/jitter/run_with_linuxenv.py b/example/jitter/run_with_linuxenv.py
index e2869699..0237cc94 100644
--- a/example/jitter/run_with_linuxenv.py
+++ b/example/jitter/run_with_linuxenv.py
@@ -2,7 +2,7 @@ from argparse import ArgumentParser
 import logging
 import re
 
-from elfesteem import elf as elf_csts
+from miasm.elfesteem import elf as elf_csts
 
 from miasm.os_dep.linux import environment, syscall
 from miasm.analysis.machine import Machine
diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py
index 0a41d038..05d28b16 100644
--- a/example/jitter/unpack_upx.py
+++ b/example/jitter/unpack_upx.py
@@ -2,7 +2,7 @@ from __future__ import print_function
 import os
 import logging
 from pdb import pm
-from elfesteem import pe
+from miasm.elfesteem import pe
 from miasm.analysis.sandbox import Sandbox_Win_x86_32
 
 # User defined methods
diff --git a/miasm/analysis/binary.py b/miasm/analysis/binary.py
index 82f83112..6dc095cf 100644
--- a/miasm/analysis/binary.py
+++ b/miasm/analysis/binary.py
@@ -131,7 +131,7 @@ class ContainerPE(Container):
 
     def parse(self, data, vm=None, **kwargs):
         from miasm.jitter.loader.pe import vm_load_pe, guess_arch
-        from elfesteem import pe_init
+        from miasm.elfesteem import pe_init
 
         # Parse signature
         if not data.startswith(b'MZ'):
@@ -178,7 +178,7 @@ class ContainerELF(Container):
         """
         from miasm.jitter.loader.elf import vm_load_elf, guess_arch, \
             fill_loc_db_with_symbols
-        from elfesteem import elf_init
+        from miasm.elfesteem import elf_init
 
         # Parse signature
         if not data.startswith(b'\x7fELF'):
diff --git a/miasm/elfesteem/__init__.py b/miasm/elfesteem/__init__.py
new file mode 100644
index 00000000..1a602f38
--- /dev/null
+++ b/miasm/elfesteem/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+
+__all__ = ['pe_init', 'elf_init', 'strpatchwork']
diff --git a/miasm/elfesteem/cstruct.py b/miasm/elfesteem/cstruct.py
new file mode 100644
index 00000000..06d2e002
--- /dev/null
+++ b/miasm/elfesteem/cstruct.py
@@ -0,0 +1,154 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+from builtins import zip
+from functools import reduce
+import struct
+
+from future.utils import PY3
+
+type_size = {}
+size2type = {}
+for t in 'B', 'H', 'I', 'Q':
+    s = struct.calcsize(t)
+    type_size[t] = s * 8
+    size2type[s * 8] = t
+
+type_size['u08'] = size2type[8]
+type_size['u16'] = size2type[16]
+type_size['u32'] = size2type[32]
+type_size['u64'] = size2type[64]
+
+
+def fix_size(fields, wsize):
+    out = []
+    for name, v in fields:
+        if v.endswith("s"):
+            pass
+        elif v == "ptr":
+            v = size2type[wsize]
+        elif not v in type_size:
+            raise ValueError("unknown Cstruct type", v)
+        else:
+            v = type_size[v]
+        out.append((name, v))
+    fields = out
+    return fields
+
+
+class Cstruct_Metaclass(type):
+
+    def __new__(cls, name, bases, dct):
+        o = super(Cstruct_Metaclass, cls).__new__(cls, name, bases, dct)
+        o._packstring =  o._packformat + \
+            "".join(x[1] for x in o._fields)
+        o._size = struct.calcsize(o._packstring)
+        return o
+
+
+class CStruct(object):
+    #__metaclass__ = Cstruct_Metaclass
+    _packformat = ""
+    _fields = []
+
+    @classmethod
+    def _from_file(cls, f):
+        return cls(f.read(cls._size))
+
+    def __init__(self, sex, wsize, *args, **kargs):
+        if sex == 1:
+            sex = '<'
+        else:
+            sex = '>'
+        # packformat enforce sex
+        if self._packformat:
+            sex = ""
+        pstr = fix_size(self._fields, wsize)
+        self._packstring = sex + self._packformat + \
+            "".join(x[1] for x in pstr)
+        self._size = struct.calcsize(self._packstring)
+
+        self._names = [x[0] for x in self._fields]
+        if kargs:
+            self.__dict__.update(kargs)
+        else:
+            if args:
+                s = args[0]
+            else:
+                s = b""
+            s += b"\x00" * self._size
+            s = s[:self._size]
+            self._unpack(s)
+
+    def _unpack(self, s):
+        disas = struct.unpack(self._packstring, s)
+        for n, v in zip(self._names, disas):
+            setattr(self, n, v)
+
+    def _pack(self):
+        return struct.pack(self._packstring,
+                           *(getattr(self, x) for x in self._names))
+
+    def _spack(self, superstruct, shift=0):
+        attr = []
+        for name in self._names:
+            s = getattr(self, name)
+            if isinstance(s, CStruct):
+                if s in superstruct:
+                    s = reduce(lambda x, y: x + len(y),
+                               superstruct[:superstruct.index(s)],
+                               0)
+                    s += shift
+                else:
+                    raise Exception("%r is not a superstructure" % s)
+            attr.append(s)
+        return struct.pack(self._packstring, *attr)
+
+    def _copy(self):
+        return self.__class__(**self.__dict__)
+
+    def __len__(self):
+        return self._size
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __bytes__(self):
+        return self._pack()
+
+    def __repr__(self):
+        return "<%s=%s>" % (self.__class__.__name__, "/".join(repr(
+            getattr(self, x[0])) for x in self._fields
+        ))
+
+    def __getitem__(self, item):  # to work with format strings
+        return getattr(self, item)
+
+    def _show(self):
+        print("##%s:" % self.__class__.__name__)
+        fmt = "%%-%is = %%r" % max(len(x[0]) for x in self._fields)
+        for fn, ft in self._fields:
+            print(fmt % (fn, getattr(self, fn)))
+
+
+class CStructStruct(object):
+
+    def __init__(self, lst, shift=0):
+        self._lst = lst
+        self._shift = shift
+
+    def __getattr__(self, attr):
+        return getattr(self._lst, attr)
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __bytes__(self):
+        return b"".join(
+            a if isinstance(a, bytes) else a._spack(self._lst, self._shift)
+            for a in self._lst
+        )
diff --git a/miasm/elfesteem/elf.py b/miasm/elfesteem/elf.py
new file mode 100644
index 00000000..bdd088b8
--- /dev/null
+++ b/miasm/elfesteem/elf.py
@@ -0,0 +1,1538 @@
+#! /usr/bin/env python
+
+from miasm.elfesteem.cstruct import CStruct
+
+class Ehdr(CStruct):
+    _fields = [ ("ident","16s"),
+                ("type","u16"),
+                ("machine","u16"),
+                ("version","u32"),
+                ("entry","ptr"),
+                ("phoff","ptr"),
+                ("shoff","ptr"),
+                ("flags","u32"),
+                ("ehsize","u16"),
+                ("phentsize","u16"),
+                ("phnum","u16"),
+                ("shentsize","u16"),
+                ("shnum","u16"),
+                ("shstrndx","u16") ]
+
+
+class Shdr(CStruct):
+    _fields = [ ("name","u32"),
+                ("type","u32"),
+                ("flags","ptr"),
+                ("addr","ptr"),
+                ("offset","ptr"),
+                ("size","ptr"),
+                ("link","u32"),
+                ("info","u32"),
+                ("addralign","ptr"),
+                ("entsize","ptr") ]
+
+class Phdr(CStruct):
+    _fields = [ ("type","u32"),
+                ("offset","u32"),
+                ("vaddr","u32"),
+                ("paddr","u32"),
+                ("filesz","u32"),
+                ("memsz","u32"),
+                ("flags","u32"),
+                ("align","u32") ]
+
+class Phdr64(CStruct):
+    _fields = [ ("type","u32"),
+                ("flags","u32"),
+                ("offset","ptr"),
+                ("vaddr","ptr"),
+                ("paddr","ptr"),
+                ("filesz","ptr"),
+                ("memsz","ptr"),
+                ("align","ptr") ]
+
+class Nhdr(CStruct):
+    _fields = [ ("namesz","u32"),
+                ("descsz","u32"),
+                ("type", "u32") ]
+
+
+class Sym32(CStruct):
+    _fields = [ ("name","u32"),
+                ("value","u32"),
+                ("size","u32"),
+                ("info","u08"),
+                ("other","u08"),
+                ("shndx","u16") ]
+
+class Sym64(CStruct):
+    _fields = [ ("name","u32"),
+                ("info","u08"),
+                ("other","u08"),
+                ("shndx","u16"),
+                ("value","u64"),
+                ("size","u64") ]
+
+class Dym(CStruct):
+    _fields = [ ("tag","u32"),
+                ("val","u32") ]
+
+class Rel32(CStruct):
+    _fields = [ ("offset","ptr"),
+                ("info","u32") ]
+
+class Rel64(CStruct):
+    _fields = [ ("offset","ptr"),
+                ("info","u64") ]
+
+class Rela32(CStruct):
+    _fields = [ ("offset","ptr"),
+                ("info","u32"),
+                ("addend","ptr") ]
+
+class Rela64(CStruct):
+    _fields = [ ("offset","ptr"),
+                ("info","u64"),
+                ("addend","ptr") ]
+
+class Dynamic(CStruct):
+    _fields = [ ("type","ptr"),
+                ("name","ptr") ]
+
+
+# Legal values for e_ident (identification indexes)
+
+EI_MAG0	=       0	# File identification
+EI_MAG1	=       1	# File identification
+EI_MAG2	=       2	# File identification
+EI_MAG3	=       3	# File identification
+EI_CLASS =      4	# File class
+EI_DATA	=       5	# Data encoding
+EI_VERSION =    6	# File version
+EI_OSABI =      7	# Operating system/ABI identification
+EI_ABIVERSION = 8	# ABI version
+EI_PAD =        9	# Start of padding bytes
+EI_NIDENT =     16	# Size of e_ident[]
+
+# Legal values for e_ident[EI_CLASS]
+
+ELFCLASSNONE =  0	# Invalid class
+ELFCLASS32 =	1	# 32-bit objects
+ELFCLASS64 =    2	# 64-bit objects
+
+# Legal values for e_ident[EI_DATA]
+
+ELFDATANONE =	0	# Invalid data encoding
+ELFDATA2LSB =	1	# Least significant byte at lowest address
+ELFDATA2MSB =	2	# Most significant byte at lowest address
+
+# Legal values for e_type (object file type).
+
+ET_NONE =         0               # No file type
+ET_REL =          1               # Relocatable file
+ET_EXEC =         2               # Executable file
+ET_DYN =          3               # Shared object file
+ET_CORE =         4               # Core file
+ET_NUM =          5               # Number of defined types
+ET_LOOS =         0xfe00         # OS-specific range start
+ET_HIOS =         0xfeff         # OS-specific range end
+ET_LOPROC =       0xff00         # Processor-specific range start
+ET_HIPROC =       0xffff         # Processor-specific range end
+
+# Legal values for e_machine (architecture).
+
+EM_NONE =         0              # No machine
+EM_M32 =          1              # AT&T WE 32100
+EM_SPARC =        2              # SUN SPARC
+EM_386 =          3              # Intel 80386
+EM_68K =          4              # Motorola m68k family
+EM_88K =          5              # Motorola m88k family
+EM_486 =          6              # Intel 80486
+EM_860 =          7              # Intel 80860
+EM_MIPS =         8              # MIPS R3000 big-endian
+EM_S370 =         9              # IBM System/370
+EM_MIPS_RS3_LE = 10              # MIPS R3000 little-endian
+
+EM_PARISC =      15              # HPPA
+EM_VPP500 =      17              # Fujitsu VPP500
+EM_SPARC32PLUS = 18              # Sun's "v8plus"
+EM_960 =         19              # Intel 80960
+EM_PPC =         20              # PowerPC
+EM_PPC64 =       21              # PowerPC 64-bit
+EM_S390 =        22              # IBM S390
+
+EM_V800 =        36              # NEC V800 series
+EM_FR20 =        37              # Fujitsu FR20
+EM_RH32 =        38              # TRW RH-32
+EM_RCE =         39              # Motorola RCE
+EM_ARM =         40              # ARM
+EM_FAKE_ALPHA =  41              # Digital Alpha
+EM_SH =          42              # Hitachi SH
+EM_SPARCV9 =     43              # SPARC v9 64-bit
+EM_TRICORE =     44              # Siemens Tricore
+EM_ARC =         45              # Argonaut RISC Core
+EM_H8_300 =      46              # Hitachi H8/300
+EM_H8_300H =     47              # Hitachi H8/300H
+EM_H8S =         48              # Hitachi H8S
+EM_H8_500 =      49              # Hitachi H8/500
+EM_IA_64 =       50              # Intel Merced
+EM_MIPS_X =      51              # Stanford MIPS-X
+EM_COLDFIRE =    52              # Motorola Coldfire
+EM_68HC12 =      53              # Motorola M68HC12
+EM_MMA =         54              # Fujitsu MMA Multimedia Accelerator*/
+EM_PCP =         55              # Siemens PCP
+EM_NCPU =        56              # Sony nCPU embeeded RISC
+EM_NDR1 =        57              # Denso NDR1 microprocessor
+EM_STARCORE =    58              # Motorola Start*Core processor
+EM_ME16 =        59              # Toyota ME16 processor
+EM_ST100 =       60              # STMicroelectronic ST100 processor
+EM_TINYJ =       61              # Advanced Logic Corp. Tinyj emb.fam*/
+EM_X86_64 =      62              # AMD x86-64 architecture
+EM_AARCH64 =     183             # Aarch64 architecture
+EM_PDSP =        63              # Sony DSP Processor
+
+EM_FX66 =        66              # Siemens FX66 microcontroller
+EM_ST9PLUS =     67              # STMicroelectronics ST9+ 8/16 mc
+EM_ST7 =         68              # STmicroelectronics ST7 8 bit mc
+EM_68HC16 =      69              # Motorola MC68HC16 microcontroller
+EM_68HC11 =      70              # Motorola MC68HC11 microcontroller
+EM_68HC08 =      71              # Motorola MC68HC08 microcontroller
+EM_68HC05 =      72              # Motorola MC68HC05 microcontroller
+EM_SVX =         73              # Silicon Graphics SVx
+EM_ST19 =        74              # STMicroelectronics ST19 8 bit mc
+EM_VAX =         75              # Digital VAX
+EM_CRIS =        76              # Axis Communications 32-bit embedded processor
+EM_JAVELIN =     77              # Infineon Technologies 32-bit embedded processor
+EM_FIREPATH =    78              # Element 14 64-bit DSP Processor
+EM_ZSP =         79              # LSI Logic 16-bit DSP Processor
+EM_MMIX =        80              # Donald Knuth's educational 64-bit processor
+EM_HUANY =       81              # Harvard University machine-independent object files
+EM_PRISM =       82              # SiTera Prism
+EM_AVR =         83              # Atmel AVR 8-bit microcontroller
+EM_FR30 =        84              # Fujitsu FR30
+EM_D10V =        85              # Mitsubishi D10V
+EM_D30V =        86              # Mitsubishi D30V
+EM_V850 =        87              # NEC v850
+EM_M32R =        88              # Mitsubishi M32R
+EM_MN10300 =     89              # Matsushita MN10300
+EM_MN10200 =     90              # Matsushita MN10200
+EM_PJ =          91              # picoJava
+EM_OPENRISC =    92              # OpenRISC 32-bit embedded processor
+EM_ARC_A5 =      93              # ARC Cores Tangent-A5
+EM_XTENSA =      94              # Tensilica Xtensa Architecture
+
+EM_ALPHA =       0x9026
+
+# Legal values for sh_type (section type).
+
+SHT_NULL =          0             # Section header table entry unused
+SHT_PROGBITS =      1             # Program data
+SHT_SYMTAB =        2             # Symbol table
+SHT_STRTAB =        3             # String table
+SHT_RELA =          4             # Relocation entries with addends
+SHT_HASH =          5             # Symbol hash table
+SHT_DYNAMIC =       6             # Dynamic linking information
+SHT_NOTE =          7             # Notes
+SHT_NOBITS =        8             # Program space with no data (bss)
+SHT_REL =           9             # Relocation entries, no addends
+SHT_SHLIB =         10            # Reserved
+SHT_DYNSYM =        11            # Dynamic linker symbol table
+SHT_INIT_ARRAY =    14            # Array of constructors
+SHT_FINI_ARRAY =    15            # Array of destructors
+SHT_PREINIT_ARRAY = 16            # Array of pre-constructors
+SHT_GROUP =         17            # Section group
+SHT_SYMTAB_SHNDX =  18            # Extended section indices
+SHT_NUM =           19            # Number of defined types.
+SHT_LOOS =          0x60000000   # Start OS-specific
+SHT_GNU_LIBLIST =   0x6ffffff7   # Prelink library list
+SHT_CHECKSUM =      0x6ffffff8   # Checksum for DSO content.
+SHT_LOSUNW =        0x6ffffffa   # Sun-specific low bound.
+SHT_SUNW_move =     0x6ffffffa
+SHT_SUNW_COMDAT =   0x6ffffffb
+SHT_SUNW_syminfo =  0x6ffffffc
+SHT_GNU_verdef =    0x6ffffffd   # Version definition section.
+SHT_GNU_verneed =   0x6ffffffe   # Version needs section.
+SHT_GNU_versym =    0x6fffffff   # Version symbol table.
+SHT_HISUNW =        0x6fffffff   # Sun-specific high bound.
+SHT_HIOS =          0x6fffffff   # End OS-specific type
+SHT_LOPROC =        0x70000000   # Start of processor-specific
+SHT_HIPROC =        0x7fffffff   # End of processor-specific
+SHT_LOUSER =        0x80000000   # Start of application-specific
+SHT_HIUSER =        0x8fffffff   # End of application-specific
+
+# Legal values for sh_flags (section flags).
+
+SHF_WRITE =            (1 << 0)   # Writable
+SHF_ALLOC =            (1 << 1)   # Occupies memory during execution
+SHF_EXECINSTR =        (1 << 2)   # Executable
+SHF_MERGE =            (1 << 4)   # Might be merged
+SHF_STRINGS =          (1 << 5)   # Contains nul-terminated strings
+SHF_INFO_LINK =        (1 << 6)   # `sh_info' contains SHT index
+SHF_LINK_ORDER =       (1 << 7)   # Preserve order after combining
+SHF_OS_NONCONFORMING = (1 << 8)   # Non-standard OS specific handling required
+SHF_GROUP =           (1 << 9)    # Section is member of a group.
+SHF_TLS =             (1 << 10)   # Section hold thread-local data.
+SHF_MASKOS =          0x0ff00000 # OS-specific.
+SHF_MASKPROC =        0xf0000000 # Processor-specific
+
+# Section group handling.
+
+GRP_COMDAT =      0x1             # Mark group as COMDAT.
+
+# Legal values for p_type (segment type).
+
+PT_NULL =         0               # Program header table entry unused
+PT_LOAD =         1               # Loadable program segment
+PT_DYNAMIC =      2               # Dynamic linking information
+PT_INTERP =       3               # Program interpreter
+PT_NOTE =         4               # Auxiliary information
+PT_SHLIB =        5               # Reserved
+PT_PHDR =         6               # Entry for header table itself
+PT_TLS =          7               # Thread-local storage segment
+PT_NUM =          8               # Number of defined types
+PT_LOOS =         0x60000000     # Start of OS-specific
+PT_GNU_EH_FRAME = 0x6474e550     # GCC .eh_frame_hdr segment
+PT_GNU_STACK =    0x6474e551     # Indicates stack executability
+PT_LOSUNW =       0x6ffffffa
+PT_SUNWBSS =      0x6ffffffa     # Sun Specific segment
+PT_SUNWSTACK =    0x6ffffffb     # Stack segment
+PT_HISUNW =       0x6fffffff
+PT_HIOS =         0x6fffffff     # End of OS-specific
+PT_LOPROC =       0x70000000     # Start of processor-specific
+PT_HIPROC =       0x7fffffff     # End of processor-specific
+
+# Legal values for p_flags (segment flags).
+
+PF_X =            (1 << 0)        # Segment is executable
+PF_W =            (1 << 1)        # Segment is writable
+PF_R =            (1 << 2)        # Segment is readable
+PF_MASKOS =       0x0ff00000     # OS-specific
+PF_MASKPROC =     0xf0000000     # Processor-specific
+
+# Legal values for note segment descriptor types for core files.
+
+NT_PRSTATUS =     1               # Contains copy of prstatus struct
+NT_FPREGSET =     2               # Contains copy of fpregset struct
+NT_PRPSINFO =     3               # Contains copy of prpsinfo struct
+NT_PRXREG =       4               # Contains copy of prxregset struct
+NT_TASKSTRUCT =   4               # Contains copy of task structure
+NT_PLATFORM =     5               # String from sysinfo(SI_PLATFORM)
+NT_AUXV =         6               # Contains copy of auxv array
+NT_GWINDOWS =     7               # Contains copy of gwindows struct
+NT_ASRS =         8               # Contains copy of asrset struct
+NT_PSTATUS =      10              # Contains copy of pstatus struct
+NT_PSINFO =       13              # Contains copy of psinfo struct
+NT_PRCRED =       14              # Contains copy of prcred struct
+NT_UTSNAME =      15              # Contains copy of utsname struct
+NT_LWPSTATUS =    16              # Contains copy of lwpstatus struct
+NT_LWPSINFO =     17              # Contains copy of lwpinfo struct
+NT_PRFPXREG =     20              # Contains copy of fprxregset struct
+
+# Legal values for the note segment descriptor types for object files.
+
+NT_VERSION =      1               # Contains a version string.
+
+# Legal values for ST_BIND subfield of st_info (symbol binding).
+# bind = Sym.info >> 4
+# val = Sym.info 0xf
+
+STB_LOCAL       = 0               # Local symbol
+STB_GLOBAL      = 1               # Global symbol
+STB_WEAK        = 2               # Weak symbol
+STB_NUM         = 3               # Number of defined types.
+STB_LOOS        = 10              # Start of OS-specific
+STB_HIOS        = 12              # End of OS-specific
+STB_LOPROC      = 13              # Start of processor-specific
+STB_HIPROC      = 15              # End of processor-specific
+
+#Legal values for ST_TYPE subfield of st_info (symbol type).
+
+STT_NOTYPE      = 0               # Symbol type is unspecified
+STT_OBJECT      = 1               # Symbol is a data object
+STT_FUNC        = 2               # Symbol is a code object
+STT_SECTION     = 3               # Symbol associated with a section
+STT_FILE        = 4               # Symbol's name is file name
+STT_COMMON      = 5               # Symbol is a common data object
+STT_TLS         = 6               # Symbol is thread-local data object*/
+STT_NUM         = 7               # Number of defined types.
+STT_LOOS        = 10              # Start of OS-specific
+STT_GNU_IFUNC   = 10              # Symbol is indirect code object
+STT_HIOS        = 12              # End of OS-specific
+STT_LOPROC      = 13              # Start of processor-specific
+STT_HIPROC      = 15              # End of processor-specific
+
+# Legal values for d_tag (dynamic entry type).
+
+DT_NULL         = 0               # Marks end of dynamic section
+DT_NEEDED       = 1               # Name of needed library
+DT_PLTRELSZ     = 2               # Size in bytes of PLT relocs
+DT_PLTGOT       = 3               # Processor defined value
+DT_HASH         = 4               # Address of symbol hash table
+DT_STRTAB       = 5               # Address of string table
+DT_SYMTAB       = 6               # Address of symbol table
+DT_RELA         = 7               # Address of Rela relocs
+DT_RELASZ       = 8               # Total size of Rela relocs
+DT_RELAENT      = 9               # Size of one Rela reloc
+DT_STRSZ        = 10              # Size of string table
+DT_SYMENT       = 11              # Size of one symbol table entry
+DT_INIT         = 12              # Address of init function
+DT_FINI         = 13              # Address of termination function
+DT_SONAME       = 14              # Name of shared object
+DT_RPATH        = 15              # Library search path (deprecated)
+DT_SYMBOLIC     = 16              # Start symbol search here
+DT_REL          = 17              # Address of Rel relocs
+DT_RELSZ        = 18              # Total size of Rel relocs
+DT_RELENT       = 19              # Size of one Rel reloc
+DT_PLTREL       = 20              # Type of reloc in PLT
+DT_DEBUG        = 21              # For debugging; unspecified
+DT_TEXTREL      = 22              # Reloc might modify .text
+DT_JMPREL       = 23              # Address of PLT relocs
+DT_BIND_NOW     = 24              # Process relocations of object
+DT_INIT_ARRAY   = 25              # Array with addresses of init fct
+DT_FINI_ARRAY   = 26              # Array with addresses of fini fct
+DT_INIT_ARRAYSZ = 27              # Size in bytes of DT_INIT_ARRAY
+DT_FINI_ARRAYSZ = 28              # Size in bytes of DT_FINI_ARRAY
+DT_RUNPATH      = 29              # Library search path
+DT_FLAGS        = 30              # Flags for the object being loaded
+DT_ENCODING     = 32              # Start of encoded range
+DT_PREINIT_ARRAY = 32             # Array with addresses of preinit fct
+DT_PREINIT_ARRAYSZ = 33           # size in bytes of DT_PREINIT_ARRAY
+DT_NUM          = 34              # Number used
+DT_LOOS         = 0x6000000d      # Start of OS-specific
+DT_HIOS         = 0x6ffff000      # End of OS-specific
+DT_LOPROC       = 0x70000000      # Start of processor-specific
+DT_HIPROC       = 0x7fffffff      # End of processor-specific
+#DT_PROCNUM      = DT_MIPS_NUM     # Most used by any processor
+
+# DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+# Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+# approach.
+DT_VALRNGLO     = 0x6ffffd00
+DT_GNU_PRELINKED = 0x6ffffdf5     # Prelinking timestamp
+DT_GNU_CONFLICTSZ = 0x6ffffdf6    # Size of conflict section
+DT_GNU_LIBLISTSZ = 0x6ffffdf7     # Size of library list
+DT_CHECKSUM     = 0x6ffffdf8
+DT_PLTPADSZ     = 0x6ffffdf9
+DT_MOVEENT      = 0x6ffffdfa
+DT_MOVESZ       = 0x6ffffdfb
+DT_FEATURE_1    = 0x6ffffdfc      # Feature selection (DTF_*).
+DT_POSFLAG_1    = 0x6ffffdfd      # Flags for DT_* entries, effecting the following DT_* entry.
+DT_SYMINSZ      = 0x6ffffdfe      # Size of syminfo table (in bytes)
+DT_SYMINENT     = 0x6ffffdff      # Entry size of syminfo
+DT_VALRNGHI     = 0x6ffffdff
+DT_VALNUM = 12
+
+# DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+# Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+#
+# If any adjustment is made to the ELF object after it has been
+# built these entries will need to be adjusted.
+DT_ADDRRNGLO    = 0x6ffffe00
+DT_GNU_CONFLICT = 0x6ffffef8      # Start of conflict section
+DT_GNU_LIBLIST  = 0x6ffffef9      # Library list
+DT_CONFIG       = 0x6ffffefa      # Configuration information.
+DT_DEPAUDIT     = 0x6ffffefb      # Dependency auditing.
+DT_AUDIT        = 0x6ffffefc      # Object auditing.
+DT_PLTPAD       = 0x6ffffefd      # PLT padding.
+DT_MOVETAB      = 0x6ffffefe      # Move table.
+DT_SYMINFO      = 0x6ffffeff      # Syminfo table.
+DT_ADDRRNGHI    = 0x6ffffeff
+DT_ADDRNUM = 10
+
+# The versioning entry types.  The next are defined as part of the
+# GNU extension.
+DT_VERSYM       = 0x6ffffff0
+
+DT_RELACOUNT    = 0x6ffffff9
+DT_RELCOUNT     = 0x6ffffffa
+
+# These were chosen by Sun.
+DT_FLAGS_1      = 0x6ffffffb      # State flags, see DF_1_* below.
+DT_VERDEF       = 0x6ffffffc      # Address of version definition table
+DT_VERDEFNUM    = 0x6ffffffd      # Number of version definitions
+DT_VERNEED      = 0x6ffffffe      # Address of table with needed versions
+DT_VERNEEDNUM   = 0x6fffffff      # Number of needed versions
+DT_VERSIONTAGNUM = 16
+
+# Sun added these machine-independent extensions in the "processor-specific"
+# range.  Be compatible.
+DT_AUXILIARY    = 0x7ffffffd      # Shared object to load before self
+DT_FILTER       = 0x7fffffff      # Shared object to get values from
+DT_EXTRANUM     = 3
+
+# Values of `d_un.d_val' in the DT_FLAGS entry.
+DF_ORIGIN       = 0x00000001      # Object may use DF_ORIGIN
+DF_SYMBOLIC     = 0x00000002      # Symbol resolutions starts here
+DF_TEXTREL      = 0x00000004      # Object contains text relocations
+DF_BIND_NOW     = 0x00000008      # No lazy binding for this object
+DF_STATIC_TLS   = 0x00000010      # Module uses the static TLS model
+
+# State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+# entry in the dynamic section.
+DF_1_NOW        = 0x00000001      # Set RTLD_NOW for this object.
+DF_1_GLOBAL     = 0x00000002      # Set RTLD_GLOBAL for this object.
+DF_1_GROUP      = 0x00000004      # Set RTLD_GROUP for this object.
+DF_1_NODELETE   = 0x00000008      # Set RTLD_NODELETE for this object.
+DF_1_LOADFLTR   = 0x00000010      # Trigger filtee loading at runtime.
+DF_1_INITFIRST  = 0x00000020      # Set RTLD_INITFIRST for this object
+DF_1_NOOPEN     = 0x00000040      # Set RTLD_NOOPEN for this object.
+DF_1_ORIGIN     = 0x00000080      # $ORIGIN must be handled.
+DF_1_DIRECT     = 0x00000100      # Direct binding enabled.
+DF_1_TRANS      = 0x00000200
+DF_1_INTERPOSE  = 0x00000400      # Object is used to interpose.
+DF_1_NODEFLIB   = 0x00000800      # Ignore default lib search path.
+DF_1_NODUMP     = 0x00001000      # Object can't be dldump'ed.
+DF_1_CONFALT    = 0x00002000      # Configuration alternative created.
+DF_1_ENDFILTEE  = 0x00004000      # Filtee terminates filters search.
+DF_1_DISPRELDNE = 0x00008000      # Disp reloc applied at build time.
+DF_1_DISPRELPND = 0x00010000      # Disp reloc applied at run-time.
+
+# Flags for the feature selection in DT_FEATURE_1.
+DTF_1_PARINIT   = 0x00000001
+DTF_1_CONFEXP   = 0x00000002
+
+# Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.
+DF_P1_LAZYLOAD  = 0x00000001      # Lazyload following object.
+DF_P1_GROUPPERM = 0x00000002      # Symbols from next object are not generally available.
+
+# GNU Versioning
+VER_FLG_BASE     = 1              # Version of the file itself, must not be used to match symbols
+VER_FLG_WEAK     = 2              # Reference to this version is weak
+VER_NEED_CURRENT = 1              # Versioning implementation number
+
+# Relocs
+
+# Motorola 68k relocations
+
+R_68K_NONE      = 0               # No reloc
+R_68K_32        = 1               # Direct 32 bit
+R_68K_16        = 2               # Direct 16 bit
+R_68K_8         = 3               # Direct 8 bit
+R_68K_PC32      = 4               # PC relative 32 bit
+R_68K_PC16      = 5               # PC relative 16 bit
+R_68K_PC8       = 6               # PC relative 8 bit
+R_68K_GOT32     = 7               # 32 bit PC relative GOT entry
+R_68K_GOT16     = 8               # 16 bit PC relative GOT entry
+R_68K_GOT8      = 9               # 8 bit PC relative GOT entry
+R_68K_GOT32O    = 10              # 32 bit GOT offset
+R_68K_GOT16O    = 11              # 16 bit GOT offset
+R_68K_GOT8O     = 12              # 8 bit GOT offset
+R_68K_PLT32     = 13              # 32 bit PC relative PLT address
+R_68K_PLT16     = 14              # 16 bit PC relative PLT address
+R_68K_PLT8      = 15              # 8 bit PC relative PLT address
+R_68K_PLT32O    = 16              # 32 bit PLT offset
+R_68K_PLT16O    = 17              # 16 bit PLT offset
+R_68K_PLT8O     = 18              # 8 bit PLT offset
+R_68K_COPY      = 19              # Copy symbol at runtime
+R_68K_GLOB_DAT  = 20              # Create GOT entry
+R_68K_JMP_SLOT  = 21              # Create PLT entry
+R_68K_RELATIVE  = 22              # Adjust by program base
+R_68K_TLS_GD32      = 25          # 32 bit GOT offset for GD
+R_68K_TLS_GD16      = 26          # 16 bit GOT offset for GD
+R_68K_TLS_GD8       = 27          # 8 bit GOT offset for GD
+R_68K_TLS_LDM32     = 28          # 32 bit GOT offset for LDM
+R_68K_TLS_LDM16     = 29          # 16 bit GOT offset for LDM
+R_68K_TLS_LDM8      = 30          # 8 bit GOT offset for LDM
+R_68K_TLS_LDO32     = 31          # 32 bit module-relative offset
+R_68K_TLS_LDO16     = 32          # 16 bit module-relative offset
+R_68K_TLS_LDO8      = 33          # 8 bit module-relative offset
+R_68K_TLS_IE32      = 34          # 32 bit GOT offset for IE
+R_68K_TLS_IE16      = 35          # 16 bit GOT offset for IE
+R_68K_TLS_IE8       = 36          # 8 bit GOT offset for IE
+R_68K_TLS_LE32      = 37          # 32 bit offset relative to static TLS block
+R_68K_TLS_LE16      = 38          # 16 bit offset relative to static TLS block
+R_68K_TLS_LE8       = 39          # 8 bit offset relative to static TLS block
+R_68K_TLS_DTPMOD32  = 40          # 32 bit module number
+R_68K_TLS_DTPREL32  = 41          # 32 bit module-relative offset
+R_68K_TLS_TPREL32   = 42          # 32 bit TP-relative offset
+# Keep this the last entry.
+R_68K_NUM       = 43
+
+# Intel 80386 relocations
+
+R_386_NONE         = 0            # No reloc
+R_386_32           = 1            # Direct 32 bit
+R_386_PC32         = 2            # PC relative 32 bit
+R_386_GOT32        = 3            # 32 bit GOT entry
+R_386_PLT32        = 4            # 32 bit PLT address
+R_386_COPY         = 5            # Copy symbol at runtime
+R_386_GLOB_DAT     = 6            # Create GOT entry
+R_386_JMP_SLOT     = 7            # Create PLT entry
+R_386_RELATIVE     = 8            # Adjust by program base
+R_386_GOTOFF       = 9            # 32 bit offset to GOT
+R_386_GOTPC        = 10           # 32 bit PC relative offset to GOT
+R_386_32PLT        = 11
+R_386_TLS_TPOFF    = 14           # Offset in static TLS block
+R_386_TLS_IE       = 15           # Address of GOT entry for static TLS block offset
+R_386_TLS_GOTIE    = 16           # GOT entry for static TLS block offset
+R_386_TLS_LE       = 17           # Offset relative to static TLS block
+R_386_TLS_GD       = 18           # Direct 32 bit for GNU version of general dynamic thread local data
+R_386_TLS_LDM      = 19           # Direct 32 bit for GNU version of local dynamic thread local data in LE code
+R_386_16           = 20
+R_386_PC16         = 21
+R_386_8            = 22
+R_386_PC8          = 23
+R_386_TLS_GD_32    = 24           # Direct 32 bit for general dynamic thread local data
+R_386_TLS_GD_PUSH  = 25           # Tag for pushl in GD TLS code
+R_386_TLS_GD_CALL  = 26           # Relocation for call to __tls_get_addr()
+R_386_TLS_GD_POP   = 27           # Tag for popl in GD TLS code
+R_386_TLS_LDM_32   = 28           # Direct 32 bit for local dynamic thread local data in LE code
+R_386_TLS_LDM_PUSH = 29           # Tag for pushl in LDM TLS code
+R_386_TLS_LDM_CALL = 30           # Relocation for call to __tls_get_addr() in LDM code
+R_386_TLS_LDM_POP  = 31           # Tag for popl in LDM TLS code
+R_386_TLS_LDO_32   = 32           # Offset relative to TLS block
+R_386_TLS_IE_32    = 33           # GOT entry for negated static TLS block offset
+R_386_TLS_LE_32    = 34           # Negated offset relative to static TLS block
+R_386_TLS_DTPMOD32 = 35           # ID of module containing symbol
+R_386_TLS_DTPOFF32 = 36           # Offset in TLS block
+R_386_TLS_TPOFF32  = 37           # Negated offset in static TLS block
+# 38?
+R_386_TLS_GOTDESC  = 39           # GOT offset for TLS descriptor.
+R_386_TLS_DESC_CALL = 40          # Marker of call through TLS descriptor for relaxation.
+R_386_TLS_DESC     = 41           # TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol.
+R_386_IRELATIVE    = 42           # Adjust indirectly by program base
+# Keep this the last entry.
+R_386_NUM          = 43
+
+# SUN SPARC relocations
+
+R_SPARC_NONE            = 0       # No reloc
+R_SPARC_8               = 1       # Direct 8 bit
+R_SPARC_16              = 2       # Direct 16 bit
+R_SPARC_32              = 3       # Direct 32 bit
+R_SPARC_DISP8           = 4       # PC relative 8 bit
+R_SPARC_DISP16          = 5       # PC relative 16 bit
+R_SPARC_DISP32          = 6       # PC relative 32 bit
+R_SPARC_WDISP30         = 7       # PC relative 30 bit shifted
+R_SPARC_WDISP22         = 8       # PC relative 22 bit shifted
+R_SPARC_HI22            = 9       # High 22 bit
+R_SPARC_22              = 10      # Direct 22 bit
+R_SPARC_13              = 11      # Direct 13 bit
+R_SPARC_LO10            = 12      # Truncated 10 bit
+R_SPARC_GOT10           = 13      # Truncated 10 bit GOT entry
+R_SPARC_GOT13           = 14      # 13 bit GOT entry
+R_SPARC_GOT22           = 15      # 22 bit GOT entry shifted
+R_SPARC_PC10            = 16      # PC relative 10 bit truncated
+R_SPARC_PC22            = 17      # PC relative 22 bit shifted
+R_SPARC_WPLT30          = 18      # 30 bit PC relative PLT address
+R_SPARC_COPY            = 19      # Copy symbol at runtime
+R_SPARC_GLOB_DAT        = 20      # Create GOT entry
+R_SPARC_JMP_SLOT        = 21      # Create PLT entry
+R_SPARC_RELATIVE        = 22      # Adjust by program base
+R_SPARC_UA32            = 23      # Direct 32 bit unaligned
+
+# Additional Sparc64 relocs.
+
+R_SPARC_PLT32           = 24      # Direct 32 bit ref to PLT entry
+R_SPARC_HIPLT22         = 25      # High 22 bit PLT entry
+R_SPARC_LOPLT10         = 26      # Truncated 10 bit PLT entry
+R_SPARC_PCPLT32         = 27      # PC rel 32 bit ref to PLT entry
+R_SPARC_PCPLT22         = 28      # PC rel high 22 bit PLT entry
+R_SPARC_PCPLT10         = 29      # PC rel trunc 10 bit PLT entry
+R_SPARC_10              = 30      # Direct 10 bit
+R_SPARC_11              = 31      # Direct 11 bit
+R_SPARC_64              = 32      # Direct 64 bit
+R_SPARC_OLO10           = 33      # 10bit with secondary 13bit addend
+R_SPARC_HH22            = 34      # Top 22 bits of direct 64 bit
+R_SPARC_HM10            = 35      # High middle 10 bits of ...
+R_SPARC_LM22            = 36      # Low middle 22 bits of ...
+R_SPARC_PC_HH22         = 37      # Top 22 bits of pc rel 64 bit
+R_SPARC_PC_HM10         = 38      # High middle 10 bit of ...
+R_SPARC_PC_LM22         = 39      # Low miggle 22 bits of ...
+R_SPARC_WDISP16         = 40      # PC relative 16 bit shifted
+R_SPARC_WDISP19         = 41      # PC relative 19 bit shifted
+R_SPARC_GLOB_JMP        = 42      # was part of v9 ABI but was removed
+R_SPARC_7               = 43      # Direct 7 bit
+R_SPARC_5               = 44      # Direct 5 bit
+R_SPARC_6               = 45      # Direct 6 bit
+R_SPARC_DISP64          = 46      # PC relative 64 bit
+R_SPARC_PLT64           = 47      # Direct 64 bit ref to PLT entry
+R_SPARC_HIX22           = 48      # High 22 bit complemented
+R_SPARC_LOX10           = 49      # Truncated 11 bit complemented
+R_SPARC_H44             = 50      # Direct high 12 of 44 bit
+R_SPARC_M44             = 51      # Direct mid 22 of 44 bit
+R_SPARC_L44             = 52      # Direct low 10 of 44 bit
+R_SPARC_REGISTER        = 53      # Global register usage
+R_SPARC_UA64            = 54      # Direct 64 bit unaligned
+R_SPARC_UA16            = 55      # Direct 16 bit unaligned
+R_SPARC_TLS_GD_HI22     = 56
+R_SPARC_TLS_GD_LO10     = 57
+R_SPARC_TLS_GD_ADD      = 58
+R_SPARC_TLS_GD_CALL     = 59
+R_SPARC_TLS_LDM_HI22    = 60
+R_SPARC_TLS_LDM_LO10    = 61
+R_SPARC_TLS_LDM_ADD     = 62
+R_SPARC_TLS_LDM_CALL    = 63
+R_SPARC_TLS_LDO_HIX22   = 64
+R_SPARC_TLS_LDO_LOX10   = 65
+R_SPARC_TLS_LDO_ADD     = 66
+R_SPARC_TLS_IE_HI22     = 67
+R_SPARC_TLS_IE_LO10     = 68
+R_SPARC_TLS_IE_LD       = 69
+R_SPARC_TLS_IE_LDX      = 70
+R_SPARC_TLS_IE_ADD      = 71
+R_SPARC_TLS_LE_HIX22    = 72
+R_SPARC_TLS_LE_LOX10    = 73
+R_SPARC_TLS_DTPMOD32    = 74
+R_SPARC_TLS_DTPMOD64    = 75
+R_SPARC_TLS_DTPOFF32    = 76
+R_SPARC_TLS_DTPOFF64    = 77
+R_SPARC_TLS_TPOFF32     = 78
+R_SPARC_TLS_TPOFF64     = 79
+R_SPARC_GOTDATA_HIX22   = 80
+R_SPARC_GOTDATA_LOX10   = 81
+R_SPARC_GOTDATA_OP_HIX22        = 82
+R_SPARC_GOTDATA_OP_LOX10        = 83
+R_SPARC_GOTDATA_OP      = 84
+R_SPARC_H34             = 85
+R_SPARC_SIZE32          = 86
+R_SPARC_SIZE64          = 87
+R_SPARC_JMP_IREL        = 248
+R_SPARC_IRELATIVE       = 249
+R_SPARC_GNU_VTINHERIT   = 250
+R_SPARC_GNU_VTENTRY     = 251
+R_SPARC_REV32           = 252
+# Keep this the last entry.
+R_SPARC_NUM             = 253
+
+# MIPS R3000 relocations
+
+R_MIPS_NONE             = 0       # No reloc
+R_MIPS_16               = 1       # Direct 16 bit
+R_MIPS_32               = 2       # Direct 32 bit
+R_MIPS_REL32            = 3       # PC relative 32 bit
+R_MIPS_26               = 4       # Direct 26 bit shifted
+R_MIPS_HI16             = 5       # High 16 bit
+R_MIPS_LO16             = 6       # Low 16 bit
+R_MIPS_GPREL16          = 7       # GP relative 16 bit
+R_MIPS_LITERAL          = 8       # 16 bit literal entry
+R_MIPS_GOT16            = 9       # 16 bit GOT entry
+R_MIPS_PC16             = 10      # PC relative 16 bit
+R_MIPS_CALL16           = 11      # 16 bit GOT entry for function
+R_MIPS_GPREL32          = 12      # GP relative 32 bit
+
+R_MIPS_SHIFT5           = 16
+R_MIPS_SHIFT6           = 17
+R_MIPS_64               = 18
+R_MIPS_GOT_DISP         = 19
+R_MIPS_GOT_PAGE         = 20
+R_MIPS_GOT_OFST         = 21
+R_MIPS_GOT_HI16         = 22
+R_MIPS_GOT_LO16         = 23
+R_MIPS_SUB              = 24
+R_MIPS_INSERT_A         = 25
+R_MIPS_INSERT_B         = 26
+R_MIPS_DELETE           = 27
+R_MIPS_HIGHER           = 28
+R_MIPS_HIGHEST          = 29
+R_MIPS_CALL_HI16        = 30
+R_MIPS_CALL_LO16        = 31
+R_MIPS_SCN_DISP         = 32
+R_MIPS_REL16            = 33
+R_MIPS_ADD_IMMEDIATE    = 34
+R_MIPS_PJUMP            = 35
+R_MIPS_RELGOT           = 36
+R_MIPS_JALR             = 37
+R_MIPS_TLS_DTPMOD32     = 38      # Module number 32 bit
+R_MIPS_TLS_DTPREL32     = 39      # Module-relative offset 32 bit
+R_MIPS_TLS_DTPMOD64     = 40      # Module number 64 bit
+R_MIPS_TLS_DTPREL64     = 41      # Module-relative offset 64 bit
+R_MIPS_TLS_GD           = 42      # 16 bit GOT offset for GD
+R_MIPS_TLS_LDM          = 43      # 16 bit GOT offset for LDM
+R_MIPS_TLS_DTPREL_HI16  = 44      # Module-relative offset, high 16 bits
+R_MIPS_TLS_DTPREL_LO16  = 45      # Module-relative offset, low 16 bits
+R_MIPS_TLS_GOTTPREL     = 46      # 16 bit GOT offset for IE
+R_MIPS_TLS_TPREL32      = 47      # TP-relative offset, 32 bit
+R_MIPS_TLS_TPREL64      = 48      # TP-relative offset, 64 bit
+R_MIPS_TLS_TPREL_HI16   = 49      # TP-relative offset, high 16 bits
+R_MIPS_TLS_TPREL_LO16   = 50      # TP-relative offset, low 16 bits
+R_MIPS_GLOB_DAT         = 51
+R_MIPS_COPY             = 126
+R_MIPS_JUMP_SLOT        = 127
+# Keep this the last entry.
+R_MIPS_NUM              = 128
+
+# HPPA relocations
+
+R_PARISC_NONE           = 0       # No reloc.
+R_PARISC_DIR32          = 1       # Direct 32-bit reference.
+R_PARISC_DIR21L         = 2       # Left 21 bits of eff. address.
+R_PARISC_DIR17R         = 3       # Right 17 bits of eff. address.
+R_PARISC_DIR17F         = 4       # 17 bits of eff. address.
+R_PARISC_DIR14R         = 6       # Right 14 bits of eff. address.
+R_PARISC_PCREL32        = 9       # 32-bit rel. address.
+R_PARISC_PCREL21L       = 10      # Left 21 bits of rel. address.
+R_PARISC_PCREL17R       = 11      # Right 17 bits of rel. address.
+R_PARISC_PCREL17F       = 12      # 17 bits of rel. address.
+R_PARISC_PCREL14R       = 14      # Right 14 bits of rel. address.
+R_PARISC_DPREL21L       = 18      # Left 21 bits of rel. address.
+R_PARISC_DPREL14R       = 22      # Right 14 bits of rel. address.
+R_PARISC_GPREL21L       = 26      # GP-relative, left 21 bits.
+R_PARISC_GPREL14R       = 30      # GP-relative, right 14 bits.
+R_PARISC_LTOFF21L       = 34      # LT-relative, left 21 bits.
+R_PARISC_LTOFF14R       = 38      # LT-relative, right 14 bits.
+R_PARISC_SECREL32       = 41      # 32 bits section rel. address.
+R_PARISC_SEGBASE        = 48      # No relocation, set segment base.
+R_PARISC_SEGREL32       = 49      # 32 bits segment rel. address.
+R_PARISC_PLTOFF21L      = 50      # PLT rel. address, left 21 bits.
+R_PARISC_PLTOFF14R      = 54      # PLT rel. address, right 14 bits.
+R_PARISC_LTOFF_FPTR32   = 57      # 32 bits LT-rel. function pointer.
+R_PARISC_LTOFF_FPTR21L  = 58      # LT-rel. fct ptr, left 21 bits.
+R_PARISC_LTOFF_FPTR14R  = 62      # LT-rel. fct ptr, right 14 bits.
+R_PARISC_FPTR64         = 64      # 64 bits function address.
+R_PARISC_PLABEL32       = 65      # 32 bits function address.
+R_PARISC_PLABEL21L      = 66      # Left 21 bits of fdesc address.
+R_PARISC_PLABEL14R      = 70      # Right 14 bits of fdesc address.
+R_PARISC_PCREL64        = 72      # 64 bits PC-rel. address.
+R_PARISC_PCREL22F       = 74      # 22 bits PC-rel. address.
+R_PARISC_PCREL14WR      = 75      # PC-rel. address, right 14 bits.
+R_PARISC_PCREL14DR      = 76      # PC rel. address, right 14 bits.
+R_PARISC_PCREL16F       = 77      # 16 bits PC-rel. address.
+R_PARISC_PCREL16WF      = 78      # 16 bits PC-rel. address.
+R_PARISC_PCREL16DF      = 79      # 16 bits PC-rel. address.
+R_PARISC_DIR64          = 80      # 64 bits of eff. address.
+R_PARISC_DIR14WR        = 83      # 14 bits of eff. address.
+R_PARISC_DIR14DR        = 84      # 14 bits of eff. address.
+R_PARISC_DIR16F         = 85      # 16 bits of eff. address.
+R_PARISC_DIR16WF        = 86      # 16 bits of eff. address.
+R_PARISC_DIR16DF        = 87      # 16 bits of eff. address.
+R_PARISC_GPREL64        = 88      # 64 bits of GP-rel. address.
+R_PARISC_GPREL14WR      = 91      # GP-rel. address, right 14 bits.
+R_PARISC_GPREL14DR      = 92      # GP-rel. address, right 14 bits.
+R_PARISC_GPREL16F       = 93      # 16 bits GP-rel. address.
+R_PARISC_GPREL16WF      = 94      # 16 bits GP-rel. address.
+R_PARISC_GPREL16DF      = 95      # 16 bits GP-rel. address.
+R_PARISC_LTOFF64        = 96      # 64 bits LT-rel. address.
+R_PARISC_LTOFF14WR      = 99      # LT-rel. address, right 14 bits.
+R_PARISC_LTOFF14DR      = 100     # LT-rel. address, right 14 bits.
+R_PARISC_LTOFF16F       = 101     # 16 bits LT-rel. address.
+R_PARISC_LTOFF16WF      = 102     # 16 bits LT-rel. address.
+R_PARISC_LTOFF16DF      = 103     # 16 bits LT-rel. address.
+R_PARISC_SECREL64       = 104     # 64 bits section rel. address.
+R_PARISC_SEGREL64       = 112     # 64 bits segment rel. address.
+R_PARISC_PLTOFF14WR     = 115     # PLT-rel. address, right 14 bits.
+R_PARISC_PLTOFF14DR     = 116     # PLT-rel. address, right 14 bits.
+R_PARISC_PLTOFF16F      = 117     # 16 bits LT-rel. address.
+R_PARISC_PLTOFF16WF     = 118     # 16 bits PLT-rel. address.
+R_PARISC_PLTOFF16DF     = 119     # 16 bits PLT-rel. address.
+R_PARISC_LTOFF_FPTR64   = 120     # 64 bits LT-rel. function ptr.
+R_PARISC_LTOFF_FPTR14WR = 123     # LT-rel. fct. ptr., right 14 bits.
+R_PARISC_LTOFF_FPTR14DR = 124     # LT-rel. fct. ptr., right 14 bits.
+R_PARISC_LTOFF_FPTR16F  = 125     # 16 bits LT-rel. function ptr.
+R_PARISC_LTOFF_FPTR16WF = 126     # 16 bits LT-rel. function ptr.
+R_PARISC_LTOFF_FPTR16DF = 127     # 16 bits LT-rel. function ptr.
+R_PARISC_LORESERVE      = 128
+R_PARISC_COPY           = 128     # Copy relocation.
+R_PARISC_IPLT           = 129     # Dynamic reloc, imported PLT
+R_PARISC_EPLT           = 130     # Dynamic reloc, exported PLT
+R_PARISC_TPREL32        = 153     # 32 bits TP-rel. address.
+R_PARISC_TPREL21L       = 154     # TP-rel. address, left 21 bits.
+R_PARISC_TPREL14R       = 158     # TP-rel. address, right 14 bits.
+R_PARISC_LTOFF_TP21L    = 162     # LT-TP-rel. address, left 21 bits.
+R_PARISC_LTOFF_TP14R    = 166     # LT-TP-rel. address, right 14 bits.*/
+R_PARISC_LTOFF_TP14F    = 167     # 14 bits LT-TP-rel. address.
+R_PARISC_TPREL64        = 216     # 64 bits TP-rel. address.
+R_PARISC_TPREL14WR      = 219     # TP-rel. address, right 14 bits.
+R_PARISC_TPREL14DR      = 220     # TP-rel. address, right 14 bits.
+R_PARISC_TPREL16F       = 221     # 16 bits TP-rel. address.
+R_PARISC_TPREL16WF      = 222     # 16 bits TP-rel. address.
+R_PARISC_TPREL16DF      = 223     # 16 bits TP-rel. address.
+R_PARISC_LTOFF_TP64     = 224     # 64 bits LT-TP-rel. address.
+R_PARISC_LTOFF_TP14WR   = 227     # LT-TP-rel. address, right 14 bits.*/
+R_PARISC_LTOFF_TP14DR   = 228     # LT-TP-rel. address, right 14 bits.*/
+R_PARISC_LTOFF_TP16F    = 229     # 16 bits LT-TP-rel. address.
+R_PARISC_LTOFF_TP16WF   = 230     # 16 bits LT-TP-rel. address.
+R_PARISC_LTOFF_TP16DF   = 231     # 16 bits LT-TP-rel. address.
+R_PARISC_GNU_VTENTRY    = 232
+R_PARISC_GNU_VTINHERIT  = 233
+R_PARISC_TLS_GD21L      = 234     # GD 21-bit left.
+R_PARISC_TLS_GD14R      = 235     # GD 14-bit right.
+R_PARISC_TLS_GDCALL     = 236     # GD call to __t_g_a.
+R_PARISC_TLS_LDM21L     = 237     # LD module 21-bit left.
+R_PARISC_TLS_LDM14R     = 238     # LD module 14-bit right.
+R_PARISC_TLS_LDMCALL    = 239     # LD module call to __t_g_a.
+R_PARISC_TLS_LDO21L     = 240     # LD offset 21-bit left.
+R_PARISC_TLS_LDO14R     = 241     # LD offset 14-bit right.
+R_PARISC_TLS_DTPMOD32   = 242     # DTP module 32-bit.
+R_PARISC_TLS_DTPMOD64   = 243     # DTP module 64-bit.
+R_PARISC_TLS_DTPOFF32   = 244     # DTP offset 32-bit.
+R_PARISC_TLS_DTPOFF64   = 245     # DTP offset 32-bit.
+R_PARISC_TLS_LE21L      = R_PARISC_TPREL21L
+R_PARISC_TLS_LE14R      = R_PARISC_TPREL14R
+R_PARISC_TLS_IE21L      = R_PARISC_LTOFF_TP21L
+R_PARISC_TLS_IE14R      = R_PARISC_LTOFF_TP14R
+R_PARISC_TLS_TPREL32    = R_PARISC_TPREL32
+R_PARISC_TLS_TPREL64    = R_PARISC_TPREL64
+R_PARISC_HIRESERVE      = 255
+
+# Alpha relocations
+
+R_ALPHA_NONE            = 0       # No reloc
+R_ALPHA_REFLONG         = 1       # Direct 32 bit
+R_ALPHA_REFQUAD         = 2       # Direct 64 bit
+R_ALPHA_GPREL32         = 3       # GP relative 32 bit
+R_ALPHA_LITERAL         = 4       # GP relative 16 bit w/optimization
+R_ALPHA_LITUSE          = 5       # Optimization hint for LITERAL
+R_ALPHA_GPDISP          = 6       # Add displacement to GP
+R_ALPHA_BRADDR          = 7       # PC+4 relative 23 bit shifted
+R_ALPHA_HINT            = 8       # PC+4 relative 16 bit shifted
+R_ALPHA_SREL16          = 9       # PC relative 16 bit
+R_ALPHA_SREL32          = 10      # PC relative 32 bit
+R_ALPHA_SREL64          = 11      # PC relative 64 bit
+R_ALPHA_GPRELHIGH       = 17      # GP relative 32 bit, high 16 bits
+R_ALPHA_GPRELLOW        = 18      # GP relative 32 bit, low 16 bits
+R_ALPHA_GPREL16         = 19      # GP relative 16 bit
+R_ALPHA_COPY            = 24      # Copy symbol at runtime
+R_ALPHA_GLOB_DAT        = 25      # Create GOT entry
+R_ALPHA_JMP_SLOT        = 26      # Create PLT entry
+R_ALPHA_RELATIVE        = 27      # Adjust by program base
+R_ALPHA_TLS_GD_HI       = 28
+R_ALPHA_TLSGD           = 29
+R_ALPHA_TLS_LDM         = 30
+R_ALPHA_DTPMOD64        = 31
+R_ALPHA_GOTDTPREL       = 32
+R_ALPHA_DTPREL64        = 33
+R_ALPHA_DTPRELHI        = 34
+R_ALPHA_DTPRELLO        = 35
+R_ALPHA_DTPREL16        = 36
+R_ALPHA_GOTTPREL        = 37
+R_ALPHA_TPREL64         = 38
+R_ALPHA_TPRELHI         = 39
+R_ALPHA_TPRELLO         = 40
+R_ALPHA_TPREL16         = 41
+# Keep this the last entry.
+R_ALPHA_NUM             = 46
+
+# PowerPC relocations
+
+R_PPC_NONE              = 0
+R_PPC_ADDR32            = 1       # 32bit absolute address
+R_PPC_ADDR24            = 2       # 26bit address, 2 bits ignored.
+R_PPC_ADDR16            = 3       # 16bit absolute address
+R_PPC_ADDR16_LO         = 4       # lower 16bit of absolute address
+R_PPC_ADDR16_HI         = 5       # high 16bit of absolute address
+R_PPC_ADDR16_HA         = 6       # adjusted high 16bit
+R_PPC_ADDR14            = 7       # 16bit address, 2 bits ignored
+R_PPC_ADDR14_BRTAKEN    = 8
+R_PPC_ADDR14_BRNTAKEN   = 9
+R_PPC_REL24             = 10      # PC relative 26 bit
+R_PPC_REL14             = 11      # PC relative 16 bit
+R_PPC_REL14_BRTAKEN     = 12
+R_PPC_REL14_BRNTAKEN    = 13
+R_PPC_GOT16             = 14
+R_PPC_GOT16_LO          = 15
+R_PPC_GOT16_HI          = 16
+R_PPC_GOT16_HA          = 17
+R_PPC_PLTREL24          = 18
+R_PPC_COPY              = 19
+R_PPC_GLOB_DAT          = 20
+R_PPC_JMP_SLOT          = 21
+R_PPC_RELATIVE          = 22
+R_PPC_LOCAL24PC         = 23
+R_PPC_UADDR32           = 24
+R_PPC_UADDR16           = 25
+R_PPC_REL32             = 26
+R_PPC_PLT32             = 27
+R_PPC_PLTREL32          = 28
+R_PPC_PLT16_LO          = 29
+R_PPC_PLT16_HI          = 30
+R_PPC_PLT16_HA          = 31
+R_PPC_SDAREL16          = 32
+R_PPC_SECTOFF           = 33
+R_PPC_SECTOFF_LO        = 34
+R_PPC_SECTOFF_HI        = 35
+R_PPC_SECTOFF_HA        = 36
+
+# PowerPC relocations defined for the TLS access ABI.
+R_PPC_TLS               = 67 # none       (sym+add)@tls
+R_PPC_DTPMOD32          = 68 # word32     (sym+add)@dtpmod
+R_PPC_TPREL16           = 69 # half16*    (sym+add)@tprel
+R_PPC_TPREL16_LO        = 70 # half16     (sym+add)@tprel@l
+R_PPC_TPREL16_HI        = 71 # half16     (sym+add)@tprel@h
+R_PPC_TPREL16_HA        = 72 # half16     (sym+add)@tprel@ha
+R_PPC_TPREL32           = 73 # word32     (sym+add)@tprel
+R_PPC_DTPREL16          = 74 # half16*    (sym+add)@dtprel
+R_PPC_DTPREL16_LO       = 75 # half16     (sym+add)@dtprel@l
+R_PPC_DTPREL16_HI       = 76 # half16     (sym+add)@dtprel@h
+R_PPC_DTPREL16_HA       = 77 # half16     (sym+add)@dtprel@ha
+R_PPC_DTPREL32          = 78 # word32     (sym+add)@dtprel
+R_PPC_GOT_TLSGD16       = 79 # half16*    (sym+add)@got@tlsgd
+R_PPC_GOT_TLSGD16_LO    = 80 # half16     (sym+add)@got@tlsgd@l
+R_PPC_GOT_TLSGD16_HI    = 81 # half16     (sym+add)@got@tlsgd@h
+R_PPC_GOT_TLSGD16_HA    = 82 # half16     (sym+add)@got@tlsgd@ha
+R_PPC_GOT_TLSLD16       = 83 # half16*    (sym+add)@got@tlsld
+R_PPC_GOT_TLSLD16_LO    = 84 # half16     (sym+add)@got@tlsld@l
+R_PPC_GOT_TLSLD16_HI    = 85 # half16     (sym+add)@got@tlsld@h
+R_PPC_GOT_TLSLD16_HA    = 86 # half16     (sym+add)@got@tlsld@ha
+R_PPC_GOT_TPREL16       = 87 # half16*    (sym+add)@got@tprel
+R_PPC_GOT_TPREL16_LO    = 88 # half16     (sym+add)@got@tprel@l
+R_PPC_GOT_TPREL16_HI    = 89 # half16     (sym+add)@got@tprel@h
+R_PPC_GOT_TPREL16_HA    = 90 # half16     (sym+add)@got@tprel@ha
+R_PPC_GOT_DTPREL16      = 91 # half16*    (sym+add)@got@dtprel
+R_PPC_GOT_DTPREL16_LO   = 92 # half16*    (sym+add)@got@dtprel@l
+R_PPC_GOT_DTPREL16_HI   = 93 # half16*    (sym+add)@got@dtprel@h
+R_PPC_GOT_DTPREL16_HA   = 94 # half16*    (sym+add)@got@dtprel@ha
+
+# The remaining relocs are from the Embedded ELF ABI, and are not in the SVR4 ELF ABI.
+R_PPC_EMB_NADDR32       = 101
+R_PPC_EMB_NADDR16       = 102
+R_PPC_EMB_NADDR16_LO    = 103
+R_PPC_EMB_NADDR16_HI    = 104
+R_PPC_EMB_NADDR16_HA    = 105
+R_PPC_EMB_SDAI16        = 106
+R_PPC_EMB_SDA2I16       = 107
+R_PPC_EMB_SDA2REL       = 108
+R_PPC_EMB_SDA21         = 109     # 16 bit offset in SDA
+R_PPC_EMB_MRKREF        = 110
+R_PPC_EMB_RELSEC16      = 111
+R_PPC_EMB_RELST_LO      = 112
+R_PPC_EMB_RELST_HI      = 113
+R_PPC_EMB_RELST_HA      = 114
+R_PPC_EMB_BIT_FLD       = 115
+R_PPC_EMB_RELSDA        = 116     # 16 bit relative offset in SDA
+
+# Diab tool relocations.
+R_PPC_DIAB_SDA21_LO     = 180     # like EMB_SDA21, but lower 16 bit
+R_PPC_DIAB_SDA21_HI     = 181     # like EMB_SDA21, but high 16 bit
+R_PPC_DIAB_SDA21_HA     = 182     # like EMB_SDA21, adjusted high 16
+R_PPC_DIAB_RELSDA_LO    = 183     # like EMB_RELSDA, but lower 16 bit
+R_PPC_DIAB_RELSDA_HI    = 184     # like EMB_RELSDA, but high 16 bit
+R_PPC_DIAB_RELSDA_HA    = 185     # like EMB_RELSDA, adjusted high 16
+
+# GNU extension to support local ifunc.
+R_PPC_IRELATIVE         = 248
+
+# GNU relocs used in PIC code sequences.
+R_PPC_REL16             = 249     # half16   (sym+add-.)
+R_PPC_REL16_LO          = 250     # half16   (sym+add-.)@l
+R_PPC_REL16_HI          = 251     # half16   (sym+add-.)@h
+R_PPC_REL16_HA          = 252     # half16   (sym+add-.)@ha
+
+# This is a phony reloc to handle any old fashioned TOC16 references that may still be in object files.
+R_PPC_TOC16             = 255
+
+# PowerPC64 relocations defined by the ABIs
+R_PPC64_NONE            = R_PPC_NONE
+R_PPC64_ADDR32          = R_PPC_ADDR32 # 32bit absolute address
+R_PPC64_ADDR24          = R_PPC_ADDR24 # 26bit address, word aligned
+R_PPC64_ADDR16          = R_PPC_ADDR16 # 16bit absolute address
+R_PPC64_ADDR16_LO       = R_PPC_ADDR16_LO # lower 16bits of address
+R_PPC64_ADDR16_HI       = R_PPC_ADDR16_HI # high 16bits of address.
+R_PPC64_ADDR16_HA       = R_PPC_ADDR16_HA # adjusted high 16bits.
+R_PPC64_ADDR14          = R_PPC_ADDR14 # 16bit address, word aligned
+R_PPC64_ADDR14_BRTAKEN  = R_PPC_ADDR14_BRTAKEN
+R_PPC64_ADDR14_BRNTAKEN = R_PPC_ADDR14_BRNTAKEN
+R_PPC64_REL24           = R_PPC_REL24 # PC-rel. 26 bit, word aligned
+R_PPC64_REL14           = R_PPC_REL14 # PC relative 16 bit
+R_PPC64_REL14_BRTAKEN   = R_PPC_REL14_BRTAKEN
+R_PPC64_REL14_BRNTAKEN  = R_PPC_REL14_BRNTAKEN
+R_PPC64_GOT16           = R_PPC_GOT16
+R_PPC64_GOT16_LO        = R_PPC_GOT16_LO
+R_PPC64_GOT16_HI        = R_PPC_GOT16_HI
+R_PPC64_GOT16_HA        = R_PPC_GOT16_HA
+
+R_PPC64_COPY            = R_PPC_COPY
+R_PPC64_GLOB_DAT        = R_PPC_GLOB_DAT
+R_PPC64_JMP_SLOT        = R_PPC_JMP_SLOT
+R_PPC64_RELATIVE        = R_PPC_RELATIVE
+
+R_PPC64_UADDR32         = R_PPC_UADDR32
+R_PPC64_UADDR16         = R_PPC_UADDR16
+R_PPC64_REL32           = R_PPC_REL32
+R_PPC64_PLT32           = R_PPC_PLT32
+R_PPC64_PLTREL32        = R_PPC_PLTREL32
+R_PPC64_PLT16_LO        = R_PPC_PLT16_LO
+R_PPC64_PLT16_HI        = R_PPC_PLT16_HI
+R_PPC64_PLT16_HA        = R_PPC_PLT16_HA
+
+R_PPC64_SECTOFF         = R_PPC_SECTOFF
+R_PPC64_SECTOFF_LO      = R_PPC_SECTOFF_LO
+R_PPC64_SECTOFF_HI      = R_PPC_SECTOFF_HI
+R_PPC64_SECTOFF_HA      = R_PPC_SECTOFF_HA
+R_PPC64_ADDR30          = 37 # word30 (S + A - P) >> 2
+R_PPC64_ADDR64          = 38 # doubleword64 S + A
+R_PPC64_ADDR16_HIGHER   = 39 # half16 #higher(S + A)
+R_PPC64_ADDR16_HIGHERA  = 40 # half16 #highera(S + A)
+R_PPC64_ADDR16_HIGHEST  = 41 # half16 #highest(S + A)
+R_PPC64_ADDR16_HIGHESTA = 42 # half16 #highesta(S + A)
+R_PPC64_UADDR64         = 43 # doubleword64 S + A
+R_PPC64_REL64           = 44 # doubleword64 S + A - P
+R_PPC64_PLT64           = 45 # doubleword64 L + A
+R_PPC64_PLTREL64        = 46 # doubleword64 L + A - P
+R_PPC64_TOC16           = 47 # half16* S + A - .TOC
+R_PPC64_TOC16_LO        = 48 # half16 #lo(S + A - .TOC.)
+R_PPC64_TOC16_HI        = 49 # half16 #hi(S + A - .TOC.)
+R_PPC64_TOC16_HA        = 50 # half16 #ha(S + A - .TOC.)
+R_PPC64_TOC             = 51 # doubleword64 .TOC
+R_PPC64_PLTGOT16        = 52 # half16* M + A
+R_PPC64_PLTGOT16_LO     = 53 # half16 #lo(M + A)
+R_PPC64_PLTGOT16_HI     = 54 # half16 #hi(M + A)
+R_PPC64_PLTGOT16_HA     = 55 # half16 #ha(M + A)
+
+R_PPC64_ADDR16_DS       = 56 # half16ds* (S + A) >> 2
+R_PPC64_ADDR16_LO_DS    = 57 # half16ds  #lo(S + A) >> 2
+R_PPC64_GOT16_DS        = 58 # half16ds* (G + A) >> 2
+R_PPC64_GOT16_LO_DS     = 59 # half16ds  #lo(G + A) >> 2
+R_PPC64_PLT16_LO_DS     = 60 # half16ds  #lo(L + A) >> 2
+R_PPC64_SECTOFF_DS      = 61 # half16ds* (R + A) >> 2
+R_PPC64_SECTOFF_LO_DS   = 62 # half16ds  #lo(R + A) >> 2
+R_PPC64_TOC16_DS        = 63 # half16ds* (S + A - .TOC.) >> 2
+R_PPC64_TOC16_LO_DS     = 64 # half16ds  #lo(S + A - .TOC.) >> 2
+R_PPC64_PLTGOT16_DS     = 65 # half16ds* (M + A) >> 2
+R_PPC64_PLTGOT16_LO_DS  = 66 # half16ds  #lo(M + A) >> 2
+
+# PowerPC64 relocations defined for the TLS access ABI.
+R_PPC64_TLS             = 67 # none       (sym+add)@tls
+R_PPC64_DTPMOD64        = 68 # doubleword64 (sym+add)@dtpmod
+R_PPC64_TPREL16         = 69 # half16*    (sym+add)@tprel
+R_PPC64_TPREL16_LO      = 70 # half16     (sym+add)@tprel@l
+R_PPC64_TPREL16_HI      = 71 # half16     (sym+add)@tprel@h
+R_PPC64_TPREL16_HA      = 72 # half16     (sym+add)@tprel@ha
+R_PPC64_TPREL64         = 73 # doubleword64 (sym+add)@tprel
+R_PPC64_DTPREL16        = 74 # half16*    (sym+add)@dtprel
+R_PPC64_DTPREL16_LO     = 75 # half16     (sym+add)@dtprel@l
+R_PPC64_DTPREL16_HI     = 76 # half16     (sym+add)@dtprel@h
+R_PPC64_DTPREL16_HA     = 77 # half16     (sym+add)@dtprel@ha
+R_PPC64_DTPREL64        = 78 # doubleword64 (sym+add)@dtprel
+R_PPC64_GOT_TLSGD16     = 79 # half16*    (sym+add)@got@tlsgd
+R_PPC64_GOT_TLSGD16_LO  = 80 # half16     (sym+add)@got@tlsgd@l
+R_PPC64_GOT_TLSGD16_HI  = 81 # half16     (sym+add)@got@tlsgd@h
+R_PPC64_GOT_TLSGD16_HA  = 82 # half16     (sym+add)@got@tlsgd@ha
+R_PPC64_GOT_TLSLD16     = 83 # half16*    (sym+add)@got@tlsld
+R_PPC64_GOT_TLSLD16_LO  = 84 # half16     (sym+add)@got@tlsld@l
+R_PPC64_GOT_TLSLD16_HI  = 85 # half16     (sym+add)@got@tlsld@h
+R_PPC64_GOT_TLSLD16_HA  = 86 # half16     (sym+add)@got@tlsld@ha
+R_PPC64_GOT_TPREL16_DS  = 87 # half16ds*  (sym+add)@got@tprel
+R_PPC64_GOT_TPREL16_LO_DS = 88 # half16ds (sym+add)@got@tprel@l
+R_PPC64_GOT_TPREL16_HI  = 89 # half16     (sym+add)@got@tprel@h
+R_PPC64_GOT_TPREL16_HA  = 90 # half16     (sym+add)@got@tprel@ha
+R_PPC64_GOT_DTPREL16_DS = 91 # half16ds*  (sym+add)@got@dtprel
+R_PPC64_GOT_DTPREL16_LO_DS = 92 # half16ds (sym+add)@got@dtprel@l
+R_PPC64_GOT_DTPREL16_HI = 93 # half16     (sym+add)@got@dtprel@h
+R_PPC64_GOT_DTPREL16_HA = 94 # half16     (sym+add)@got@dtprel@ha
+R_PPC64_TPREL16_DS      = 95 # half16ds*  (sym+add)@tprel
+R_PPC64_TPREL16_LO_DS   = 96 # half16ds   (sym+add)@tprel@l
+R_PPC64_TPREL16_HIGHER  = 97 # half16     (sym+add)@tprel@higher
+R_PPC64_TPREL16_HIGHERA = 98 # half16     (sym+add)@tprel@highera
+R_PPC64_TPREL16_HIGHEST = 99 # half16     (sym+add)@tprel@highest
+R_PPC64_TPREL16_HIGHESTA = 100 # half16   (sym+add)@tprel@highesta
+R_PPC64_DTPREL16_DS     = 101 # half16ds* (sym+add)@dtprel
+R_PPC64_DTPREL16_LO_DS  = 102 # half16ds  (sym+add)@dtprel@l
+R_PPC64_DTPREL16_HIGHER = 103 # half16    (sym+add)@dtprel@higher
+R_PPC64_DTPREL16_HIGHERA = 104 # half16   (sym+add)@dtprel@highera
+R_PPC64_DTPREL16_HIGHEST = 105 # half16   (sym+add)@dtprel@highest
+R_PPC64_DTPREL16_HIGHESTA = 106 # half16  (sym+add)@dtprel@highesta
+
+# GNU extension to support local ifunc.
+R_PPC64_JMP_IREL        = 247
+R_PPC64_IRELATIVE       = 248
+R_PPC64_REL16           = 249     # half16   (sym+add-.)
+R_PPC64_REL16_LO        = 250     # half16   (sym+add-.)@l
+R_PPC64_REL16_HI        = 251     # half16   (sym+add-.)@h
+R_PPC64_REL16_HA        = 252     # half16   (sym+add-.)@ha
+
+# PowerPC64 specific values for the Dyn d_tag field.
+DT_PPC64_GLINK  = (DT_LOPROC + 0)
+DT_PPC64_OPD    = (DT_LOPROC + 1)
+DT_PPC64_OPDSZ  = (DT_LOPROC + 2)
+DT_PPC64_NUM    = 3
+
+# ARM relocations
+
+R_ARM_NONE              = 0       # No reloc
+R_ARM_PC24              = 1       # PC relative 26 bit branch
+R_ARM_ABS32             = 2       # Direct 32 bit
+R_ARM_REL32             = 3       # PC relative 32 bit
+R_ARM_PC13              = 4
+R_ARM_ABS16             = 5       # Direct 16 bit
+R_ARM_ABS12             = 6       # Direct 12 bit
+R_ARM_THM_ABS5          = 7
+R_ARM_ABS8              = 8       # Direct 8 bit
+R_ARM_SBREL32           = 9
+R_ARM_THM_PC22          = 10
+R_ARM_THM_PC8           = 11
+R_ARM_AMP_VCALL9        = 12
+R_ARM_SWI24             = 13      # Obsolete static relocation.
+R_ARM_TLS_DESC          = 13      # Dynamic relocation.
+R_ARM_THM_SWI8          = 14
+R_ARM_XPC25             = 15
+R_ARM_THM_XPC22         = 16
+R_ARM_TLS_DTPMOD32      = 17      # ID of module containing symbol
+R_ARM_TLS_DTPOFF32      = 18      # Offset in TLS block
+R_ARM_TLS_TPOFF32       = 19      # Offset in static TLS block
+R_ARM_COPY              = 20      # Copy symbol at runtime
+R_ARM_GLOB_DAT          = 21      # Create GOT entry
+R_ARM_JUMP_SLOT         = 22      # Create PLT entry
+R_ARM_RELATIVE          = 23      # Adjust by program base
+R_ARM_GOTOFF            = 24      # 32 bit offset to GOT
+R_ARM_GOTPC             = 25      # 32 bit PC relative offset to GOT
+R_ARM_GOT32             = 26      # 32 bit GOT entry
+R_ARM_PLT32             = 27      # 32 bit PLT address
+R_ARM_ALU_PCREL_7_0     = 32
+R_ARM_ALU_PCREL_15_8    = 33
+R_ARM_ALU_PCREL_23_15   = 34
+R_ARM_LDR_SBREL_11_0    = 35
+R_ARM_ALU_SBREL_19_12   = 36
+R_ARM_ALU_SBREL_27_20   = 37
+R_ARM_TLS_GOTDESC       = 90
+R_ARM_TLS_CALL          = 91
+R_ARM_TLS_DESCSEQ       = 92
+R_ARM_THM_TLS_CALL      = 93
+R_ARM_GNU_VTENTRY       = 100
+R_ARM_GNU_VTINHERIT     = 101
+R_ARM_THM_PC11          = 102     # thumb unconditional branch
+R_ARM_THM_PC9           = 103     # thumb conditional branch
+R_ARM_TLS_GD32          = 104     # PC-rel 32 bit for global dynamic thread local data
+R_ARM_TLS_LDM32         = 105     # PC-rel 32 bit for local dynamic thread local data
+R_ARM_TLS_LDO32         = 106     # 32 bit offset relative to TLS block
+R_ARM_TLS_IE32          = 107     # PC-rel 32 bit for GOT entry of static TLS block offset
+R_ARM_TLS_LE32          = 108     # 32 bit offset relative to static TLS block
+R_ARM_THM_TLS_DESCSEQ   = 129
+R_ARM_IRELATIVE         = 160
+R_ARM_RXPC25            = 249
+R_ARM_RSBREL32          = 250
+R_ARM_THM_RPC22         = 251
+R_ARM_RREL32            = 252
+R_ARM_RABS22            = 253
+R_ARM_RPC24             = 254
+R_ARM_RBASE             = 255
+# Keep this the last entry.
+R_ARM_NUM               = 256
+
+# IA-64 relocations
+
+R_IA64_NONE             = 0x00    # none
+R_IA64_IMM14            = 0x21    # symbol + addend, add imm14
+R_IA64_IMM22            = 0x22    # symbol + addend, add imm22
+R_IA64_IMM64            = 0x23    # symbol + addend, mov imm64
+R_IA64_DIR32MSB         = 0x24    # symbol + addend, data4 MSB
+R_IA64_DIR32LSB         = 0x25    # symbol + addend, data4 LSB
+R_IA64_DIR64MSB         = 0x26    # symbol + addend, data8 MSB
+R_IA64_DIR64LSB         = 0x27    # symbol + addend, data8 LSB
+R_IA64_GPREL22          = 0x2a    # @gprel(sym + add), add imm22
+R_IA64_GPREL64I         = 0x2b    # @gprel(sym + add), mov imm64
+R_IA64_GPREL32MSB       = 0x2c    # @gprel(sym + add), data4 MSB
+R_IA64_GPREL32LSB       = 0x2d    # @gprel(sym + add), data4 LSB
+R_IA64_GPREL64MSB       = 0x2e    # @gprel(sym + add), data8 MSB
+R_IA64_GPREL64LSB       = 0x2f    # @gprel(sym + add), data8 LSB
+R_IA64_LTOFF22          = 0x32    # @ltoff(sym + add), add imm22
+R_IA64_LTOFF64I         = 0x33    # @ltoff(sym + add), mov imm64
+R_IA64_PLTOFF22         = 0x3a    # @pltoff(sym + add), add imm22
+R_IA64_PLTOFF64I        = 0x3b    # @pltoff(sym + add), mov imm64
+R_IA64_PLTOFF64MSB      = 0x3e    # @pltoff(sym + add), data8 MSB
+R_IA64_PLTOFF64LSB      = 0x3f    # @pltoff(sym + add), data8 LSB
+R_IA64_FPTR64I          = 0x43    # @fptr(sym + add), mov imm64
+R_IA64_FPTR32MSB        = 0x44    # @fptr(sym + add), data4 MSB
+R_IA64_FPTR32LSB        = 0x45    # @fptr(sym + add), data4 LSB
+R_IA64_FPTR64MSB        = 0x46    # @fptr(sym + add), data8 MSB
+R_IA64_FPTR64LSB        = 0x47    # @fptr(sym + add), data8 LSB
+R_IA64_PCREL60B         = 0x48    # @pcrel(sym + add), brl
+R_IA64_PCREL21B         = 0x49    # @pcrel(sym + add), ptb, call
+R_IA64_PCREL21M         = 0x4a    # @pcrel(sym + add), chk.s
+R_IA64_PCREL21F         = 0x4b    # @pcrel(sym + add), fchkf
+R_IA64_PCREL32MSB       = 0x4c    # @pcrel(sym + add), data4 MSB
+R_IA64_PCREL32LSB       = 0x4d    # @pcrel(sym + add), data4 LSB
+R_IA64_PCREL64MSB       = 0x4e    # @pcrel(sym + add), data8 MSB
+R_IA64_PCREL64LSB       = 0x4f    # @pcrel(sym + add), data8 LSB
+R_IA64_LTOFF_FPTR22     = 0x52    # @ltoff(@fptr(s+a)), imm22
+R_IA64_LTOFF_FPTR64I    = 0x53    # @ltoff(@fptr(s+a)), imm64
+R_IA64_LTOFF_FPTR32MSB  = 0x54    # @ltoff(@fptr(s+a)), data4 MSB
+R_IA64_LTOFF_FPTR32LSB  = 0x55    # @ltoff(@fptr(s+a)), data4 LSB
+R_IA64_LTOFF_FPTR64MSB  = 0x56    # @ltoff(@fptr(s+a)), data8 MSB
+R_IA64_LTOFF_FPTR64LSB  = 0x57    # @ltoff(@fptr(s+a)), data8 LSB
+R_IA64_SEGREL32MSB      = 0x5c    # @segrel(sym + add), data4 MSB
+R_IA64_SEGREL32LSB      = 0x5d    # @segrel(sym + add), data4 LSB
+R_IA64_SEGREL64MSB      = 0x5e    # @segrel(sym + add), data8 MSB
+R_IA64_SEGREL64LSB      = 0x5f    # @segrel(sym + add), data8 LSB
+R_IA64_SECREL32MSB      = 0x64    # @secrel(sym + add), data4 MSB
+R_IA64_SECREL32LSB      = 0x65    # @secrel(sym + add), data4 LSB
+R_IA64_SECREL64MSB      = 0x66    # @secrel(sym + add), data8 MSB
+R_IA64_SECREL64LSB      = 0x67    # @secrel(sym + add), data8 LSB
+R_IA64_REL32MSB         = 0x6c    # data 4 + REL
+R_IA64_REL32LSB         = 0x6d    # data 4 + REL
+R_IA64_REL64MSB         = 0x6e    # data 8 + REL
+R_IA64_REL64LSB         = 0x6f    # data 8 + REL
+R_IA64_LTV32MSB         = 0x74    # symbol + addend, data4 MSB
+R_IA64_LTV32LSB         = 0x75    # symbol + addend, data4 LSB
+R_IA64_LTV64MSB         = 0x76    # symbol + addend, data8 MSB
+R_IA64_LTV64LSB         = 0x77    # symbol + addend, data8 LSB
+R_IA64_PCREL21BI        = 0x79    # @pcrel(sym + add), 21bit inst
+R_IA64_PCREL22          = 0x7a    # @pcrel(sym + add), 22bit inst
+R_IA64_PCREL64I         = 0x7b    # @pcrel(sym + add), 64bit inst
+R_IA64_IPLTMSB          = 0x80    # dynamic reloc, imported PLT, MSB
+R_IA64_IPLTLSB          = 0x81    # dynamic reloc, imported PLT, LSB
+R_IA64_COPY             = 0x84    # copy relocation
+R_IA64_SUB              = 0x85    # Addend and symbol difference
+R_IA64_LTOFF22X         = 0x86    # LTOFF22, relaxable.
+R_IA64_LDXMOV           = 0x87    # Use of LTOFF22X.
+R_IA64_TPREL14          = 0x91    # @tprel(sym + add), imm14
+R_IA64_TPREL22          = 0x92    # @tprel(sym + add), imm22
+R_IA64_TPREL64I         = 0x93    # @tprel(sym + add), imm64
+R_IA64_TPREL64MSB       = 0x96    # @tprel(sym + add), data8 MSB
+R_IA64_TPREL64LSB       = 0x97    # @tprel(sym + add), data8 LSB
+R_IA64_LTOFF_TPREL22    = 0x9a    # @ltoff(@tprel(s+a)), imm2
+R_IA64_DTPMOD64MSB      = 0xa6    # @dtpmod(sym + add), data8 MSB
+R_IA64_DTPMOD64LSB      = 0xa7    # @dtpmod(sym + add), data8 LSB
+R_IA64_LTOFF_DTPMOD22   = 0xaa    # @ltoff(@dtpmod(sym + add)), imm22
+R_IA64_DTPREL14         = 0xb1    # @dtprel(sym + add), imm14
+R_IA64_DTPREL22         = 0xb2    # @dtprel(sym + add), imm22
+R_IA64_DTPREL64I        = 0xb3    # @dtprel(sym + add), imm64
+R_IA64_DTPREL32MSB      = 0xb4    # @dtprel(sym + add), data4 MSB
+R_IA64_DTPREL32LSB      = 0xb5    # @dtprel(sym + add), data4 LSB
+R_IA64_DTPREL64MSB      = 0xb6    # @dtprel(sym + add), data8 MSB
+R_IA64_DTPREL64LSB      = 0xb7    # @dtprel(sym + add), data8 LSB
+R_IA64_LTOFF_DTPREL22   = 0xba    # @ltoff(@dtprel(s+a)), imm22
+
+# SH relocations
+
+R_SH_NONE               = 0
+R_SH_DIR32              = 1
+R_SH_REL32              = 2
+R_SH_DIR8WPN            = 3
+R_SH_IND12W             = 4
+R_SH_DIR8WPL            = 5
+R_SH_DIR8WPZ            = 6
+R_SH_DIR8BP             = 7
+R_SH_DIR8W              = 8
+R_SH_DIR8L              = 9
+R_SH_SWITCH16           = 25
+R_SH_SWITCH32           = 26
+R_SH_USES               = 27
+R_SH_COUNT              = 28
+R_SH_ALIGN              = 29
+R_SH_CODE               = 30
+R_SH_DATA               = 31
+R_SH_LABEL              = 32
+R_SH_SWITCH8            = 33
+R_SH_GNU_VTINHERIT      = 34
+R_SH_GNU_VTENTRY        = 35
+R_SH_TLS_GD_32          = 144
+R_SH_TLS_LD_32          = 145
+R_SH_TLS_LDO_32         = 146
+R_SH_TLS_IE_32          = 147
+R_SH_TLS_LE_32          = 148
+R_SH_TLS_DTPMOD32       = 149
+R_SH_TLS_DTPOFF32       = 150
+R_SH_TLS_TPOFF32        = 151
+R_SH_GOT32              = 160
+R_SH_PLT32              = 161
+R_SH_COPY               = 162
+R_SH_GLOB_DAT           = 163
+R_SH_JMP_SLOT           = 164
+R_SH_RELATIVE           = 165
+R_SH_GOTOFF             = 166
+R_SH_GOTPC              = 167
+# Keep this the last entry.
+R_SH_NUM                = 256
+
+# S/390 relocations
+
+R_390_NONE              = 0       # No reloc.
+R_390_8                 = 1       # Direct 8 bit.
+R_390_12                = 2       # Direct 12 bit.
+R_390_16                = 3       # Direct 16 bit.
+R_390_32                = 4       # Direct 32 bit.
+R_390_PC32              = 5       # PC relative 32 bit.
+R_390_GOT12             = 6       # 12 bit GOT offset.
+R_390_GOT32             = 7       # 32 bit GOT offset.
+R_390_PLT32             = 8       # 32 bit PC relative PLT address.
+R_390_COPY              = 9       # Copy symbol at runtime.
+R_390_GLOB_DAT          = 10      # Create GOT entry.
+R_390_JMP_SLOT          = 11      # Create PLT entry.
+R_390_RELATIVE          = 12      # Adjust by program base.
+R_390_GOTOFF32          = 13      # 32 bit offset to GOT.
+R_390_GOTPC             = 14      # 32 bit PC relative offset to GOT.
+R_390_GOT16             = 15      # 16 bit GOT offset.
+R_390_PC16              = 16      # PC relative 16 bit.
+R_390_PC16DBL           = 17      # PC relative 16 bit shifted by 1.
+R_390_PLT16DBL          = 18      # 16 bit PC rel. PLT shifted by 1.
+R_390_PC32DBL           = 19      # PC relative 32 bit shifted by 1.
+R_390_PLT32DBL          = 20      # 32 bit PC rel. PLT shifted by 1.
+R_390_GOTPCDBL          = 21      # 32 bit PC rel. GOT shifted by 1.
+R_390_64                = 22      # Direct 64 bit.
+R_390_PC64              = 23      # PC relative 64 bit.
+R_390_GOT64             = 24      # 64 bit GOT offset.
+R_390_PLT64             = 25      # 64 bit PC relative PLT address.
+R_390_GOTENT            = 26      # 32 bit PC rel. to GOT entry >> 1.
+R_390_GOTOFF16          = 27      # 16 bit offset to GOT.
+R_390_GOTOFF64          = 28      # 64 bit offset to GOT.
+R_390_GOTPLT12          = 29      # 12 bit offset to jump slot.
+R_390_GOTPLT16          = 30      # 16 bit offset to jump slot.
+R_390_GOTPLT32          = 31      # 32 bit offset to jump slot.
+R_390_GOTPLT64          = 32      # 64 bit offset to jump slot.
+R_390_GOTPLTENT         = 33      # 32 bit rel. offset to jump slot.
+R_390_PLTOFF16          = 34      # 16 bit offset from GOT to PLT.
+R_390_PLTOFF32          = 35      # 32 bit offset from GOT to PLT.
+R_390_PLTOFF64          = 36      # 16 bit offset from GOT to PLT.
+R_390_TLS_LOAD          = 37      # Tag for load insn in TLS code.
+R_390_TLS_GDCALL        = 38      # Tag for function call in general dynamic TLS code.
+R_390_TLS_LDCALL        = 39      # Tag for function call in local dynamic TLS code.
+R_390_TLS_GD32          = 40      # Direct 32 bit for general dynamic thread local data.
+R_390_TLS_GD64          = 41      # Direct 64 bit for general dynamic thread local data.
+R_390_TLS_GOTIE12       = 42      # 12 bit GOT offset for static TLS block offset.
+R_390_TLS_GOTIE32       = 43      # 32 bit GOT offset for static TLS block offset.
+R_390_TLS_GOTIE64       = 44      # 64 bit GOT offset for static TLS block offset.
+R_390_TLS_LDM32         = 45      # Direct 32 bit for local dynamic thread local data in LE code.
+R_390_TLS_LDM64         = 46      # Direct 64 bit for local dynamic thread local data in LE code.
+R_390_TLS_IE32          = 47      # 32 bit address of GOT entry for negated static TLS block offset.
+R_390_TLS_IE64          = 48      # 64 bit address of GOT entry for negated static TLS block offset.
+R_390_TLS_IEENT         = 49      # 32 bit rel. offset to GOT entry for negated static TLS block offset.
+R_390_TLS_LE32          = 50      # 32 bit negated offset relative to static TLS block.
+R_390_TLS_LE64          = 51      # 64 bit negated offset relative to static TLS block.
+R_390_TLS_LDO32         = 52      # 32 bit offset relative to TLS block.
+R_390_TLS_LDO64         = 53      # 64 bit offset relative to TLS block.
+R_390_TLS_DTPMOD        = 54      # ID of module containing symbol.
+R_390_TLS_DTPOFF        = 55      # Offset in TLS block.
+R_390_TLS_TPOFF         = 56      # Negated offset in static TLS block.
+R_390_20                = 57      # Direct 20 bit.
+R_390_GOT20             = 58      # 20 bit GOT offset.
+R_390_GOTPLT20          = 59      # 20 bit offset to jump slot.
+R_390_TLS_GOTIE20       = 60      # 20 bit GOT offset for static TLS block offset.
+# Keep this the last entry.
+R_390_NUM               = 61
+
+
+# CRIS relocations.
+R_CRIS_NONE             = 0
+R_CRIS_8                = 1
+R_CRIS_16               = 2
+R_CRIS_32               = 3
+R_CRIS_8_PCREL          = 4
+R_CRIS_16_PCREL         = 5
+R_CRIS_32_PCREL         = 6
+R_CRIS_GNU_VTINHERIT    = 7
+R_CRIS_GNU_VTENTRY      = 8
+R_CRIS_COPY             = 9
+R_CRIS_GLOB_DAT         = 10
+R_CRIS_JUMP_SLOT        = 11
+R_CRIS_RELATIVE         = 12
+R_CRIS_16_GOT           = 13
+R_CRIS_32_GOT           = 14
+R_CRIS_16_GOTPLT        = 15
+R_CRIS_32_GOTPLT        = 16
+R_CRIS_32_GOTREL        = 17
+R_CRIS_32_PLT_GOTREL    = 18
+R_CRIS_32_PLT_PCREL     = 19
+
+R_CRIS_NUM              = 20
+
+
+# AMD x86-64 relocations.
+R_X86_64_NONE           = 0       # No reloc
+R_X86_64_64             = 1       # Direct 64 bit
+R_X86_64_PC32           = 2       # PC relative 32 bit signed
+R_X86_64_GOT32          = 3       # 32 bit GOT entry
+R_X86_64_PLT32          = 4       # 32 bit PLT address
+R_X86_64_COPY           = 5       # Copy symbol at runtime
+R_X86_64_GLOB_DAT       = 6       # Create GOT entry
+R_X86_64_JUMP_SLOT      = 7       # Create PLT entry
+R_X86_64_RELATIVE       = 8       # Adjust by program base
+R_X86_64_GOTPCREL       = 9       # 32 bit signed PC relative offset to GOT
+R_X86_64_32             = 10      # Direct 32 bit zero extended
+R_X86_64_32S            = 11      # Direct 32 bit sign extended
+R_X86_64_16             = 12      # Direct 16 bit zero extended
+R_X86_64_PC16           = 13      # 16 bit sign extended pc relative
+R_X86_64_8              = 14      # Direct 8 bit sign extended
+R_X86_64_PC8            = 15      # 8 bit sign extended pc relative
+R_X86_64_DTPMOD64       = 16      # ID of module containing symbol
+R_X86_64_DTPOFF64       = 17      # Offset in module's TLS block
+R_X86_64_TPOFF64        = 18      # Offset in initial TLS block
+R_X86_64_TLSGD          = 19      # 32 bit signed PC relative offset to two GOT entries for GD symbol
+R_X86_64_TLSLD          = 20      # 32 bit signed PC relative offset to two GOT entries for LD symbol
+R_X86_64_DTPOFF32       = 21      # Offset in TLS block
+R_X86_64_GOTTPOFF       = 22      # 32 bit signed PC relative offset to GOT entry for IE symbol
+R_X86_64_TPOFF32        = 23      # Offset in initial TLS block
+R_X86_64_PC64           = 24      # PC relative 64 bit
+R_X86_64_GOTOFF64       = 25      # 64 bit offset to GOT
+R_X86_64_GOTPC32        = 26      # 32 bit signed pc relative offset to GOT
+R_X86_64_GOT64          = 27      # 64-bit GOT entry offset
+R_X86_64_GOTPCREL64     = 28      # 64-bit PC relative offset to GOT entry
+R_X86_64_GOTPC64        = 29      # 64-bit PC relative offset to GOT
+R_X86_64_GOTPLT64       = 30      # like GOT64, says PLT entry needed
+R_X86_64_PLTOFF64       = 31      # 64-bit GOT relative offset to PLT entry
+R_X86_64_SIZE32         = 32      # Size of symbol plus 32-bit addend
+R_X86_64_SIZE64         = 33      # Size of symbol plus 64-bit addend
+R_X86_64_GOTPC32_TLSDESC = 34     # GOT offset for TLS descriptor.
+R_X86_64_TLSDESC_CALL   = 35      # Marker for call through TLS descriptor.
+R_X86_64_TLSDESC        = 36      # TLS descriptor.
+R_X86_64_IRELATIVE      = 37      # Adjust indirectly by program base
+
+R_X86_64_NUM            = 38
+
+
+# AM33 relocations.
+R_MN10300_NONE          = 0       # No reloc.
+R_MN10300_32            = 1       # Direct 32 bit.
+R_MN10300_16            = 2       # Direct 16 bit.
+R_MN10300_8             = 3       # Direct 8 bit.
+R_MN10300_PCREL32       = 4       # PC-relative 32-bit.
+R_MN10300_PCREL16       = 5       # PC-relative 16-bit signed.
+R_MN10300_PCREL8        = 6       # PC-relative 8-bit signed.
+R_MN10300_GNU_VTINHERIT = 7       # Ancient C++ vtable garbage...
+R_MN10300_GNU_VTENTRY   = 8       # ... collection annotation.
+R_MN10300_24            = 9       # Direct 24 bit.
+R_MN10300_GOTPC32       = 10      # 32-bit PCrel offset to GOT.
+R_MN10300_GOTPC16       = 11      # 16-bit PCrel offset to GOT.
+R_MN10300_GOTOFF32      = 12      # 32-bit offset from GOT.
+R_MN10300_GOTOFF24      = 13      # 24-bit offset from GOT.
+R_MN10300_GOTOFF16      = 14      # 16-bit offset from GOT.
+R_MN10300_PLT32         = 15      # 32-bit PCrel to PLT entry.
+R_MN10300_PLT16         = 16      # 16-bit PCrel to PLT entry.
+R_MN10300_GOT32         = 17      # 32-bit offset to GOT entry.
+R_MN10300_GOT24         = 18      # 24-bit offset to GOT entry.
+R_MN10300_GOT16         = 19      # 16-bit offset to GOT entry.
+R_MN10300_COPY          = 20      # Copy symbol at runtime.
+R_MN10300_GLOB_DAT      = 21      # Create GOT entry.
+R_MN10300_JMP_SLOT      = 22      # Create PLT entry.
+R_MN10300_RELATIVE      = 23      # Adjust by program base.
+
+R_MN10300_NUM           = 24
+
+
+# M32R relocs.
+R_M32R_NONE             = 0       # No reloc.
+R_M32R_16               = 1       # Direct 16 bit.
+R_M32R_32               = 2       # Direct 32 bit.
+R_M32R_24               = 3       # Direct 24 bit.
+R_M32R_10_PCREL         = 4       # PC relative 10 bit shifted.
+R_M32R_18_PCREL         = 5       # PC relative 18 bit shifted.
+R_M32R_26_PCREL         = 6       # PC relative 26 bit shifted.
+R_M32R_HI16_ULO         = 7       # High 16 bit with unsigned low.
+R_M32R_HI16_SLO         = 8       # High 16 bit with signed low.
+R_M32R_LO16             = 9       # Low 16 bit.
+R_M32R_SDA16            = 10      # 16 bit offset in SDA.
+R_M32R_GNU_VTINHERIT    = 11
+R_M32R_GNU_VTENTRY      = 12
+# M32R relocs use SHT_RELA.
+R_M32R_16_RELA          = 33      # Direct 16 bit.
+R_M32R_32_RELA          = 34      # Direct 32 bit.
+R_M32R_24_RELA          = 35      # Direct 24 bit.
+R_M32R_10_PCREL_RELA    = 36      # PC relative 10 bit shifted.
+R_M32R_18_PCREL_RELA    = 37      # PC relative 18 bit shifted.
+R_M32R_26_PCREL_RELA    = 38      # PC relative 26 bit shifted.
+R_M32R_HI16_ULO_RELA    = 39      # High 16 bit with unsigned low
+R_M32R_HI16_SLO_RELA    = 40      # High 16 bit with signed low
+R_M32R_LO16_RELA        = 41      # Low 16 bit
+R_M32R_SDA16_RELA       = 42      # 16 bit offset in SDA
+R_M32R_RELA_GNU_VTINHERIT       = 43
+R_M32R_RELA_GNU_VTENTRY = 44
+R_M32R_REL32            = 45      # PC relative 32 bit.
+
+R_M32R_GOT24            = 48      # 24 bit GOT entry
+R_M32R_26_PLTREL        = 49      # 26 bit PC relative to PLT shifted
+R_M32R_COPY             = 50      # Copy symbol at runtime
+R_M32R_GLOB_DAT         = 51      # Create GOT entry
+R_M32R_JMP_SLOT         = 52      # Create PLT entry
+R_M32R_RELATIVE         = 53      # Adjust by program base
+R_M32R_GOTOFF           = 54      # 24 bit offset to GOT
+R_M32R_GOTPC24          = 55      # 24 bit PC relative offset to GOT
+R_M32R_GOT16_HI_ULO     = 56      # High 16 bit GOT entry with unsigned low
+R_M32R_GOT16_HI_SLO     = 57      # High 16 bit GOT entry with signed low
+R_M32R_GOT16_LO         = 58      # Low 16 bit GOT entry
+R_M32R_GOTPC_HI_ULO     = 59      # High 16 bit PC relative offset to GOT with unsigned low
+R_M32R_GOTPC_HI_SLO     = 60      # High 16 bit PC relative offset to GOT with signed low
+R_M32R_GOTPC_LO         = 61      # Low 16 bit PC relative offset to GOT
+R_M32R_GOTOFF_HI_ULO    = 62      # High 16 bit offset to GOT with unsigned low
+R_M32R_GOTOFF_HI_SLO    = 63      # High 16 bit offset to GOT with signed low
+R_M32R_GOTOFF_LO        = 64      # Low 16 bit offset to GOT
+R_M32R_NUM              = 256     # Keep this the last entry.
diff --git a/miasm/elfesteem/elf_init.py b/miasm/elfesteem/elf_init.py
new file mode 100644
index 00000000..14a37eb5
--- /dev/null
+++ b/miasm/elfesteem/elf_init.py
@@ -0,0 +1,878 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+from builtins import range
+import logging
+import struct
+
+from future.utils import PY3, with_metaclass
+
+from miasm.core.utils import force_bytes
+from miasm.elfesteem import cstruct
+from miasm.elfesteem import elf
+from miasm.elfesteem.strpatchwork import StrPatchwork
+
+log = logging.getLogger("elfparse")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARN)
+
+
+def printable(string):
+    if isinstance(string, bytes):
+        return "".join(
+            c.decode() if b" " <= c < b"~" else "."
+            for c in (string[i:i+1] for i in range(len(string)))
+        )
+    return string
+
+
+class StructWrapper_metaclass(type):
+
+    def __new__(cls, name, bases, dct):
+        wrapped = dct["wrapped"]
+        if wrapped is not None:  # XXX: make dct lookup look into base classes
+            for fname, v in wrapped._fields:
+                dct[fname] = property(dct.pop("get_" + fname,
+                                              lambda self, fname=fname: getattr(
+                                                  self.cstr, fname)),
+                                      dct.pop("set_" + fname,
+                                              lambda self, v, fname=fname: setattr(
+                                                  self.cstr, fname, v)),
+                                      dct.pop("del_" + fname, None))
+        return type.__new__(cls, name, bases, dct)
+
+
+class StructWrapper(with_metaclass(StructWrapper_metaclass, object)):
+
+    wrapped = None
+
+    def __init__(self, parent, sex, size, *args, **kargs):
+        self.cstr = self.wrapped(sex, size, *args, **kargs)
+        self.parent = parent
+
+    def __getitem__(self, item):
+        return getattr(self, item)
+
+    def __repr__(self):
+        return "<W-" + repr(self.cstr)[1:]
+
+    def __str__(self):
+        return str(self.cstr)
+
+    def __bytes__(self):
+        return bytes(self.cstr)
+
+
+class WEhdr(StructWrapper):
+    wrapped = elf.Ehdr
+
+    def set_shstrndx(self, val):
+        self.cstr.shstrndx = val
+
+
+class WSym32(StructWrapper):
+    wrapped = elf.Sym32
+
+    def get_name(self):
+        return self.parent.linksection.get_name(self.cstr.name)
+
+
+class WSym64(StructWrapper):
+    wrapped = elf.Sym64
+
+    def get_name(self):
+        return self.parent.linksection.get_name(self.cstr.name)
+
+
+class WRel32(StructWrapper):
+    wrapped = elf.Rel32
+    wrapped._fields.append(("sym", "u32"))
+    wrapped._fields.append(("type", "u08"))
+
+    def get_sym(self):
+        return self.parent.linksection.symtab[self.cstr.info >> 8].name
+
+    def get_type(self):
+        return self.cstr.info & 0xff
+
+
+class WRel64(StructWrapper):
+    wrapped = elf.Rel64
+    wrapped._fields.append(("sym", "u32"))
+    wrapped._fields.append(("type", "u32"))
+
+    def get_sym(self):
+        return self.parent.linksection.symtab[self.cstr.info >> 32].name
+
+    def get_type(self):
+        return self.cstr.info & 0xffffffff
+
+
+class WRela32(WRel32):
+    wrapped = elf.Rela32
+    wrapped._fields.append(("sym", "u32"))
+    wrapped._fields.append(("type", "u08"))
+
+    def get_sym(self):
+        return self.parent.linksection.symtab[self.cstr.info >> 8].name
+
+    def get_type(self):
+        return self.cstr.info & 0xff
+
+
+class WRela64(WRel64):
+    wrapped = elf.Rela64
+    wrapped._fields.append(("sym", "u32"))
+    wrapped._fields.append(("type", "u32"))
+
+    def get_sym(self):
+        return self.parent.linksection.symtab[self.cstr.info >> 32].name
+
+    def get_type(self):
+        return self.cstr.info & 0xffffffff
+
+
+class WShdr(StructWrapper):
+    wrapped = elf.Shdr
+
+    def get_name(self):
+        return self.parent.parent._shstr.get_name(self.cstr.name)
+
+
+class WDynamic(StructWrapper):
+    wrapped = elf.Dynamic
+
+    def get_name(self):
+        if self.type == elf.DT_NEEDED:
+            return self.parent.linksection.get_name(self.cstr.name)
+        return self.cstr.name
+
+
+class WPhdr(StructWrapper):
+    wrapped = elf.Phdr
+
+
+class WPhdr64(StructWrapper):
+    wrapped = elf.Phdr64
+
+
+class WNhdr(StructWrapper):
+    wrapped = elf.Nhdr
+
+
+class ContentManager(object):
+
+    def __get__(self, owner, x):
+        if hasattr(owner, '_content'):
+            return owner._content
+
+    def __set__(self, owner, new_content):
+        owner.resize(len(owner._content), len(new_content))
+        owner._content = StrPatchwork(new_content)
+        owner.parse_content(owner.sex, owner.size)
+
+    def __delete__(self, owner):
+        self.__set__(owner, None)
+
+
+# Sections
+
+class Section_metaclass(type):
+
+    def __new__(cls, name, bases, dct):
+        o = type.__new__(cls, name, bases, dct)
+        if name != "Section":
+            Section.register(o)
+        return o
+
+    def register(cls, o):
+        if o.sht is not None:
+            cls.sectypes[o.sht] = o
+
+    def __call__(cls, parent, sex, size, shstr=None):
+        sh = None
+        if shstr is not None:
+            sh = WShdr(None, sex, size, shstr)
+            if sh.type in Section.sectypes:
+                cls = Section.sectypes[sh.type]
+        i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
+        if sh is not None:
+            sh.parent = i
+        i.__init__(parent, sh)
+        return i
+
+
+class Section(with_metaclass(Section_metaclass, object)):
+
+    sectypes = {}
+    content = ContentManager()
+
+    def resize(self, old, new):
+        self.sh.size += new - old
+        self.parent.resize(self, new - old)
+        if self.phparent:
+            self.phparent.resize(self, new - old)
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        pass
+
+    def get_linksection(self):
+        return self.parent[self.sh.link]
+
+    def set_linksection(self, val):
+        if isinstance(val, Section):
+            val = self.parent.shlist.find(val)
+        if type(val) is int:
+            self.sh.link = val
+    linksection = property(get_linksection, set_linksection)
+
+    def get_infosection(self):
+        # XXX info may not be in sh list ?!?
+        if not self.sh.info in self.parent:
+            return None
+        return self.parent[self.sh.info]
+
+    def set_infosection(self, val):
+        if isinstance(val, Section):
+            val = self.parent.shlist.find(val)
+        if type(val) is int:
+            self.sh.info = val
+    infosection = property(get_infosection, set_infosection)
+
+    def __init__(self, parent, sh=None):
+        self.parent = parent
+        self.phparent = None
+        self.sh = sh
+        self._content = b""
+
+    def __repr__(self):
+        r = "{%(name)s ofs=%(offset)#x sz=%(size)#x addr=%(addr)#010x}" % self.sh
+        return r
+
+
+class NullSection(Section):
+    sht = elf.SHT_NULL
+
+    def get_name(self, ofs):
+        # XXX check this
+        return b""
+
+
+class ProgBits(Section):
+    sht = elf.SHT_PROGBITS
+
+
+class HashSection(Section):
+    sht = elf.SHT_HASH
+
+
+class NoBitsSection(Section):
+    sht = elf.SHT_NOBITS
+
+
+class ShLibSection(Section):
+    sht = elf.SHT_SHLIB
+
+
+class InitArray(Section):
+    sht = elf.SHT_INIT_ARRAY
+
+
+class FiniArray(Section):
+    sht = elf.SHT_FINI_ARRAY
+
+
+class GroupSection(Section):
+    sht = elf.SHT_GROUP
+
+
+class SymTabSHIndeces(Section):
+    sht = elf.SHT_SYMTAB_SHNDX
+
+
+class GNUVerSym(Section):
+    sht = elf.SHT_GNU_versym
+
+
+class GNUVerNeed(Section):
+    sht = elf.SHT_GNU_verneed
+
+
+class GNUVerDef(Section):
+    sht = elf.SHT_GNU_verdef
+
+
+class GNULibLIst(Section):
+    sht = elf.SHT_GNU_LIBLIST
+
+
+class CheckSumSection(Section):
+    sht = elf.SHT_CHECKSUM
+
+
+class NoteSection(Section):
+    sht = elf.SHT_NOTE
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        c = self.content
+        hsz = 12
+        self.notes = []
+        # XXX: c may not be aligned?
+        while len(c) > hsz:
+            note = WNhdr(self, sex, size, c)
+            namesz, descsz = note.namesz, note.descsz
+            name = c[hsz:hsz + namesz]
+            desc = c[hsz + namesz:hsz + namesz + descsz]
+            c = c[hsz + namesz + descsz:]
+            self.notes.append((note.type, name, desc))
+
+
+class Dynamic(Section):
+    sht = elf.SHT_DYNAMIC
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        c = self.content
+        self.dyntab = []
+        self.dynamic = {}
+        sz = self.sh.entsize
+        idx = 0
+        while len(c) > sz*idx:
+            s = c[sz*idx:sz*(idx+1)]
+            idx += 1
+            dyn = WDynamic(self, sex, size, s)
+            self.dyntab.append(dyn)
+            if isinstance(dyn.name, str):
+                self[dyn.name] = dyn
+
+    def __setitem__(self, item, value):
+        if isinstance(item, bytes):
+            self.dynamic[item] = value
+            return
+        if isinstance(item, str):
+            self.symbols[item.encode()] = value
+            return
+        self.dyntab[item] = value
+
+    def __getitem__(self, item):
+        if isinstance(item, bytes):
+            return self.dynamic[item]
+        if isinstance(item, str):
+            return self.dynamic[item.encode()]
+        return self.dyntab[item]
+
+
+class StrTable(Section):
+    sht = elf.SHT_STRTAB
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        self.res = {}
+        c = self.content
+        q = 0
+        index = 0
+        l = len(c)
+        while index < l:
+            p = c.find(b"\x00", index)
+            if p < 0:
+                log.warning("Missing trailing 0 for string [%s]" % c)  # XXX
+                p = len(c) - index
+            self.res[index] = c[index:p]
+            # print q, c[:p]
+            index = p + 1
+            # q += p+1
+            # c = c[p+1:]
+
+    def get_name(self, ofs):
+        return self.content[ofs:self.content.find(b'\x00', start=ofs)]
+
+    def add_name(self, name):
+        name = force_bytes(name)
+        name = name + b"\x00"
+        if name in self.content:
+            return self.content.find(name)
+        n = len(self.content)
+        self.content = bytes(self.content) + name
+        return n
+
+    def mod_name(self, name, new_name):
+        s = bytes(self.content)
+        name_b = b'\x00%s\x00' % name.encode()
+        if not name_b in s:
+            raise ValueError('Unknown name %r' % name)
+        self.content = s.replace(
+            name_b,
+            b'\x00%s\x00' % new_name.encode()
+        )
+        return len(self.content)
+
+
+class SymTable(Section):
+    sht = elf.SHT_SYMTAB
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        c = self.content
+        self.symtab = []
+        self.symbols = {}
+        sz = self.sh.entsize
+        index = 0
+        l = len(c)
+        if size == 32:
+            WSym = WSym32
+        elif size == 64:
+            WSym = WSym64
+        else:
+            ValueError('unknown size')
+        while index < l:
+            s = c[index:index + sz]
+            index += sz
+            sym = WSym(self, sex, size, s)
+            self.symtab.append(sym)
+            self[sym.name] = sym
+
+    def __getitem__(self, item):
+        if isinstance(item, bytes):
+            return self.symbols[item]
+        if isinstance(item, str):
+            return self.symbols[item.encode()]
+        return self.symtab[item]
+
+    def __setitem__(self, item, value):
+        if isinstance(item, bytes):
+            self.symbols[item] = value
+            return
+        if isinstance(item, str):
+            self.symbols[item.encode()] = value
+            return
+        self.symtab[item] = value
+
+
+class DynSymTable(SymTable):
+    sht = elf.SHT_DYNSYM
+
+
+class RelTable(Section):
+    sht = elf.SHT_REL
+
+    def parse_content(self, sex, size):
+        self.sex, self.size = sex, size
+        if size == 32:
+            WRel = WRel32
+        elif size == 64:
+            WRel = WRel64
+        else:
+            ValueError('unknown size')
+        c = self.content
+        self.reltab = []
+        self.rel = {}
+        sz = self.sh.entsize
+
+        idx = 0
+        while len(c) > sz*idx:
+            s = c[sz*idx:sz*(idx+1)]
+            idx += 1
+            rel = WRel(self, sex, size, s)
+            self.reltab.append(rel)
+            if rel.parent.linksection != self.parent.shlist[0]:
+                self.rel[rel.sym] = rel
+
+
+class RelATable(RelTable):
+    sht = elf.SHT_RELA
+
+# Section List
+
+
+class SHList(object):
+
+    def __init__(self, parent, sex, size):
+        self.parent = parent
+        self.shlist = []
+        ehdr = self.parent.Ehdr
+        of1 = ehdr.shoff
+        if not of1:  # No SH table
+            return
+        for i in range(ehdr.shnum):
+            of2 = of1 + ehdr.shentsize
+            shstr = parent[of1:of2]
+            self.shlist.append(Section(self, sex, size, shstr=shstr))
+            of1 = of2
+        self._shstr = self.shlist[ehdr.shstrndx]
+
+        for s in self.shlist:
+            if not isinstance(s, NoBitsSection):
+                s._content = StrPatchwork(
+                    parent[s.sh.offset: s.sh.offset + s.sh.size]
+                )
+        # Follow dependencies when initializing sections
+        zero = self.shlist[0]
+        todo = self.shlist[1:]
+        done = []
+        while todo:
+            s = todo.pop(0)
+            if ((s.linksection == zero or s.linksection in done) and
+                    (s.infosection in [zero, None] or s.infosection in done)):
+                done.append(s)
+                s.parse_content(sex, size)
+            else:
+                todo.append(s)
+        for s in self.shlist:
+            self.do_add_section(s)
+
+    def do_add_section(self, section):
+        n = section.sh.name
+        if n.startswith(b"."):
+            n = n[1:]
+        n = printable(n).replace(".", "_").replace("-", "_")
+        setattr(self, n, section)  # xxx
+
+    def append(self, item):
+        self.do_add_section(item)
+        self.shlist.append(item)
+
+    def __getitem__(self, item):
+        return self.shlist[item]
+
+    def __repr__(self):
+        rep = ["#  section         offset   size   addr     flags"]
+        for i, s in enumerate(self.shlist):
+            l = "%(name)-15s %(offset)08x %(size)06x %(addr)08x %(flags)x " % s.sh
+            l = ("%2i " % i) + l + s.__class__.__name__
+            rep.append(l)
+        return "\n".join(rep)
+
+    def __bytes__(self):
+        return b"".join(
+            bytes(s.sh) for s in self.shlist
+        )
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return bytes(self)
+
+    def resize(self, sec, diff):
+        for s in self.shlist:
+            if s.sh.offset > sec.sh.offset:
+                s.sh.offset += diff
+        if self.parent.Ehdr.shoff > sec.sh.offset:
+            self.parent.Ehdr.shoff += diff
+        if self.parent.Ehdr.phoff > sec.sh.offset:
+            self.parent.Ehdr.phoff += diff
+
+# Program Header List
+
+
+class ProgramHeader(object):
+
+    def __init__(self, parent, sex, size, phstr):
+        self.parent = parent
+        self.ph = WPhdr(self, sex, size, phstr)
+        self.shlist = []
+        for s in self.parent.parent.sh:
+            if isinstance(s, NullSection):
+                continue
+            if ((isinstance(s, NoBitsSection) and s.sh.offset == self.ph.offset + self.ph.filesz)
+               or self.ph.offset <= s.sh.offset < self.ph.offset + self.ph.filesz):
+                s.phparent = self
+                self.shlist.append(s)
+
+    def resize(self, sec, diff):
+        self.ph.filesz += diff
+        self.ph.memsz += diff
+        self.parent.resize(sec, diff)
+
+
+class ProgramHeader64(object):
+
+    def __init__(self, parent, sex, size, phstr):
+        self.parent = parent
+        self.ph = WPhdr64(self, sex, size, phstr)
+        self.shlist = []
+        for s in self.parent.parent.sh:
+            if isinstance(s, NullSection):
+                continue
+            if ((isinstance(s, NoBitsSection) and s.sh.offset == self.ph.offset + self.ph.filesz)
+               or self.ph.offset <= s.sh.offset < self.ph.offset + self.ph.filesz):
+                s.phparent = self
+                self.shlist.append(s)
+
+    def resize(self, sec, diff):
+        self.ph.filesz += diff
+        self.ph.memsz += diff
+        self.parent.resize(sec, diff)
+
+
+class PHList(object):
+
+    def __init__(self, parent, sex, size):
+        self.parent = parent
+        self.phlist = []
+        ehdr = self.parent.Ehdr
+        of1 = ehdr.phoff
+        for i in range(ehdr.phnum):
+            of2 = of1 + ehdr.phentsize
+            phstr = parent[of1:of2]
+            if size == 32:
+                self.phlist.append(ProgramHeader(self, sex, size, phstr))
+            else:
+                self.phlist.append(ProgramHeader64(self, sex, size, phstr))
+            of1 = of2
+
+    def __getitem__(self, item):
+        return self.phlist[item]
+
+    def __repr__(self):
+        r = ["   offset filesz vaddr    memsz"]
+        for i, p in enumerate(self.phlist):
+            l = "%(offset)07x %(filesz)06x %(vaddr)08x %(memsz)07x %(type)02x %(flags)01x" % p.ph
+            l = ("%2i " % i) + l
+            r.append(l)
+            r.append("   " + " ".join(printable(s.sh.name) for s in p.shlist))
+        return "\n".join(r)
+
+    def __bytes__(self):
+        return b"".join(
+            bytes(p.ph) for p in self.phlist
+        )
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__(self)
+
+    def resize(self, sec, diff):
+        for p in self.phlist:
+            if p.ph.offset > sec.sh.offset:
+                p.ph.offset += diff
+            if p.ph.vaddr > sec.phparent.ph.vaddr + sec.sh.offset:
+                p.ph.vaddr += diff
+            if p.ph.paddr > sec.phparent.ph.paddr + sec.sh.offset:
+                p.ph.paddr += diff
+
+
+class virt(object):
+
+    def __init__(self, x):
+        self.parent = x
+
+    def get_rvaitem(self, start, stop=None):
+        if stop == None:
+            s = self.parent.getsectionbyvad(start)
+            if s:
+                start = start - s.sh.addr
+            else:
+                s = self.parent.getphbyvad(start)
+                if s:
+                    start = start - s.ph.vaddr
+            if not s:
+                return [(None, start)]
+            return [(s, start)]
+        total_len = stop - start
+
+        virt_item = []
+        while total_len:
+            s = self.parent.getsectionbyvad(start)
+            if not s:
+                s = self.parent.getphbyvad(start)
+            if not s:
+                raise ValueError('unknown rva address! %x' % start)
+            if isinstance(s, ProgramHeader) or isinstance(s, ProgramHeader64):
+                s_max = s.ph.filesz
+                s_start = start - s.ph.vaddr
+                s_stop = stop - s.ph.vaddr
+            else:
+                s_max = s.sh.size
+                s_start = start - s.sh.addr
+                s_stop = stop - s.sh.addr
+            if s_stop > s_max:
+                s_stop = s_max
+
+            s_len = s_stop - s_start
+            if s_len == 0:
+                raise ValueError('empty section! %x' % start)
+            total_len -= s_len
+            start += s_len
+            n_item = slice(s_start, s_stop)
+            virt_item.append((s, n_item))
+        return virt_item
+
+    def item2virtitem(self, item):
+        if not type(item) is slice:  # integer
+            return self.get_rvaitem(item)
+        start = item.start
+        stop = item.stop
+        assert(item.step is None)
+        return self.get_rvaitem(start, stop)
+
+    def get(self, ad_start, ad_stop=None):
+        rva_items = self.get_rvaitem(ad_start, ad_stop)
+        data_out = b""
+        for s, n_item in rva_items:
+            if not (isinstance(s, ProgramHeader) or isinstance(s, ProgramHeader64)):
+                data_out += s.content.__getitem__(n_item)
+                continue
+            if not type(n_item) is slice:
+                n_item = slice(n_item, n_item + 1, 1)
+            start = n_item.start + s.ph.offset
+            stop = n_item.stop + s.ph.offset
+            if n_item.step != None:
+                step = n_item.step + s.ph.offset
+            else:
+                step = None
+            n_item = slice(start, stop, step)
+            # data_out += self.parent.content.__s.content.__getitem__(n_item)
+            data_out += self.parent.content.__getitem__(n_item)
+
+        return data_out
+
+    def set(self, item, data):
+        if not type(item) is slice:
+            item = slice(item, item + len(data), None)
+        virt_item = self.item2virtitem(item)
+        if not virt_item:
+            return
+        off = 0
+        for s, n_item in virt_item:
+            if isinstance(s, ProgBits):
+                i = slice(off, n_item.stop + off - n_item.start, n_item.step)
+
+                data_slice = data.__getitem__(i)
+                s.content.__setitem__(n_item, data_slice)
+                off = i.stop
+            else:
+                raise ValueError('TODO XXX')
+
+        return
+
+    def __getitem__(self, item):
+        if isinstance(item, slice):
+            assert(item.step is None)
+            return self.get(item.start, item.stop)
+        else:
+            return self.get(item)
+
+    def __setitem__(self, item, data):
+        if isinstance(item, slice):
+            rva = item.start
+        else:
+            rva = item
+        self.set(rva, data)
+
+    def max_addr(self):
+        # the maximum virtual address is found by retrieving the maximum
+        # possible virtual address, either from the program entries, and
+        # section entries. if there is no such object, raise an error.
+        l = 0
+        if self.parent.ph.phlist:
+            for phdr in self.parent.ph.phlist:
+                l = max(l, phdr.ph.vaddr + phdr.ph.memsz)
+        if self.parent.sh.shlist:
+            for shdr in self.parent.sh.shlist:
+                l = max(l, shdr.sh.addr + shdr.sh.size)
+        if not l:
+            raise ValueError('maximum virtual address not found !')
+        return l
+
+    def is_addr_in(self, ad):
+        return self.parent.is_in_virt_address(ad)
+
+    def find(self, pattern, start=0):
+        sections = []
+        offset = start
+        for s in self.parent.ph:
+            s_max = s.ph.memsz  # max(s.ph.filesz, s.ph.memsz)
+            if offset < s.ph.vaddr + s_max:
+                sections.append(s)
+
+        if not sections:
+            return -1
+        offset -= sections[0].ph.vaddr
+        if offset < 0:
+            offset = 0
+        for s in sections:
+            data = self.parent.content[s.ph.offset:s.ph.offset + s.ph.filesz]
+            ret = data.find(pattern, offset)
+            if ret != -1:
+                return ret + s.ph.vaddr  # self.parent.rva2virt(s.addr + ret)
+            offset = 0
+        return -1
+
+# ELF object
+
+
+class ELF(object):
+
+    def __init__(self, elfstr):
+        self._content = elfstr
+        self.parse_content()
+
+        self._virt = virt(self)
+
+    def get_virt(self):
+        return self._virt
+    virt = property(get_virt)
+
+    content = ContentManager()
+
+    def parse_content(self):
+        h = self.content[:8]
+        self.size = struct.unpack('B', h[4:5])[0] * 32
+        self.sex = struct.unpack('B', h[5:6])[0]
+        self.Ehdr = WEhdr(self, self.sex, self.size, self.content)
+        self.sh = SHList(self, self.sex, self.size)
+        self.ph = PHList(self, self.sex, self.size)
+
+    def resize(self, old, new):
+        pass
+
+    def __getitem__(self, item):
+        return self.content[item]
+
+    def build_content(self):
+        c = StrPatchwork()
+        c[0] = bytes(self.Ehdr)
+        c[self.Ehdr.phoff] = bytes(self.ph)
+        for s in self.sh:
+            c[s.sh.offset] = bytes(s.content)
+        c[self.Ehdr.shoff] = bytes(self.sh)
+        return bytes(c)
+
+    def __bytes__(self):
+        return self.build_content()
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return bytes(self)
+
+    def getphbyvad(self, ad):
+        for s in self.ph:
+            if s.ph.vaddr <= ad < s.ph.vaddr + s.ph.memsz:
+                return s
+
+    def getsectionbyvad(self, ad):
+        for s in self.sh:
+            if s.sh.addr <= ad < s.sh.addr + s.sh.size:
+                return s
+
+    def getsectionbyname(self, name):
+        name = force_bytes(name)
+        for s in self.sh:
+            try:
+                if s.sh.name.strip(b'\x00') == name:
+                    return s
+            except UnicodeDecodeError:
+                pass
+        return None
+
+    def is_in_virt_address(self, ad):
+        for s in self.sh:
+            if s.sh.addr <= ad < s.sh.addr + s.sh.size:
+                return True
+        return False
diff --git a/miasm/elfesteem/minidump.py b/miasm/elfesteem/minidump.py
new file mode 100644
index 00000000..ee2be8a0
--- /dev/null
+++ b/miasm/elfesteem/minidump.py
@@ -0,0 +1,545 @@
+"""Constants and structures associated to Minidump format
+Based on: http://amnesia.gtisc.gatech.edu/~moyix/minidump.py
+"""
+from future.utils import viewitems
+
+from future.builtins import int as int_types
+from miasm.elfesteem.new_cstruct import CStruct
+
+class Enumeration(object):
+    """Stand for an enumeration type"""
+
+    def __init__(self, enum_info):
+        """enum_info: {name: value}"""
+        self._enum_info = enum_info
+        self._inv_info = dict((v, k) for k, v in viewitems(enum_info))
+
+    def __getitem__(self, key):
+        """Helper: assume that string is for key, integer is for value"""
+        if isinstance(key, int_types):
+            return self._inv_info[key]
+        return self._enum_info[key]
+
+    def __getattr__(self, key):
+        if key in self._enum_info:
+            return self._enum_info[key]
+        raise AttributeError
+
+    def from_value(self, value):
+        return self._inv_info[value]
+
+
+class Rva(CStruct):
+    """Relative Virtual Address
+    Note: RVA in Minidump means "file offset"
+    """
+    _fields = [("rva", "u32"),
+    ]
+
+
+minidumpType = Enumeration({
+    # MINIDUMP_TYPE
+    # https://msdn.microsoft.com/en-us/library/ms680519(v=vs.85).aspx
+    "MiniDumpNormal"                          : 0x00000000,
+    "MiniDumpWithDataSegs"                    : 0x00000001,
+    "MiniDumpWithFullMemory"                  : 0x00000002,
+    "MiniDumpWithHandleData"                  : 0x00000004,
+    "MiniDumpFilterMemory"                    : 0x00000008,
+    "MiniDumpScanMemory"                      : 0x00000010,
+    "MiniDumpWithUnloadedModules"             : 0x00000020,
+    "MiniDumpWithIndirectlyReferencedMemory"  : 0x00000040,
+    "MiniDumpFilterModulePaths"               : 0x00000080,
+    "MiniDumpWithProcessThreadData"           : 0x00000100,
+    "MiniDumpWithPrivateReadWriteMemory"      : 0x00000200,
+    "MiniDumpWithoutOptionalData"             : 0x00000400,
+    "MiniDumpWithFullMemoryInfo"              : 0x00000800,
+    "MiniDumpWithThreadInfo"                  : 0x00001000,
+    "MiniDumpWithCodeSegs"                    : 0x00002000,
+    "MiniDumpWithoutAuxiliaryState"           : 0x00004000,
+    "MiniDumpWithFullAuxiliaryState"          : 0x00008000,
+    "MiniDumpWithPrivateWriteCopyMemory"      : 0x00010000,
+    "MiniDumpIgnoreInaccessibleMemory"        : 0x00020000,
+    "MiniDumpWithTokenInformation"            : 0x00040000,
+    "MiniDumpWithModuleHeaders"               : 0x00080000,
+    "MiniDumpFilterTriage"                    : 0x00100000,
+    "MiniDumpValidTypeFlags"                  : 0x001fffff,
+})
+
+class MinidumpHDR(CStruct):
+    """MINIDUMP_HEADER
+    https://msdn.microsoft.com/en-us/library/ms680378(VS.85).aspx
+    """
+    _fields = [("Magic", "u32"), # MDMP
+               ("Version", "u16"),
+               ("ImplementationVersion", "u16"),
+               ("NumberOfStreams", "u32"),
+               ("StreamDirectoryRva", "Rva"),
+               ("Checksum", "u32"),
+               ("TimeDateStamp", "u32"),
+               ("Flags", "u32")
+    ]
+
+class LocationDescriptor(CStruct):
+    """MINIDUMP_LOCATION_DESCRIPTOR
+    https://msdn.microsoft.com/en-us/library/ms680383(v=vs.85).aspx
+    """
+    _fields = [("DataSize", "u32"),
+               ("Rva", "Rva"),
+    ]
+
+
+streamType = Enumeration({
+    # MINIDUMP_STREAM_TYPE
+    # https://msdn.microsoft.com/en-us/library/ms680394(v=vs.85).aspx
+    "UnusedStream"               : 0,
+    "ReservedStream0"            : 1,
+    "ReservedStream1"            : 2,
+    "ThreadListStream"           : 3,
+    "ModuleListStream"           : 4,
+    "MemoryListStream"           : 5,
+    "ExceptionStream"            : 6,
+    "SystemInfoStream"           : 7,
+    "ThreadExListStream"         : 8,
+    "Memory64ListStream"         : 9,
+    "CommentStreamA"             : 10,
+    "CommentStreamW"             : 11,
+    "HandleDataStream"           : 12,
+    "FunctionTableStream"        : 13,
+    "UnloadedModuleListStream"   : 14,
+    "MiscInfoStream"             : 15,
+    "MemoryInfoListStream"       : 16,
+    "ThreadInfoListStream"       : 17,
+    "HandleOperationListStream"  : 18,
+    "LastReservedStream"         : 0xffff,
+})
+
+class StreamDirectory(CStruct):
+    """MINIDUMP_DIRECTORY
+    https://msdn.microsoft.com/en-us/library/ms680365(VS.85).aspx
+    """
+    _fields = [("StreamType", "u32"),
+               ("Location", "LocationDescriptor"),
+    ]
+
+    @property
+    def pretty_name(self):
+        return streamType[self.StreamType]
+
+
+class FixedFileInfo(CStruct):
+    """VS_FIXEDFILEINFO
+    https://msdn.microsoft.com/en-us/library/ms646997(v=vs.85).aspx
+    """
+    _fields = [("dwSignature", "u32"),
+               ("dwStrucVersion", "u32"),
+               ("dwFileVersionMS", "u32"),
+               ("dwFileVersionLS", "u32"),
+               ("dwProductVersionMS", "u32"),
+               ("dwProductVersionLS", "u32"),
+               ("dwFileFlagsMask", "u32"),
+               ("dwFileFlags", "u32"),
+               ("dwFileOS", "u32"),
+               ("dwFileType", "u32"),
+               ("dwFileSubtype", "u32"),
+               ("dwFileDateMS", "u32"),
+               ("dwFileDateLS", "u32"),
+    ]
+
+class MinidumpString(CStruct):
+    """MINIDUMP_STRING
+    https://msdn.microsoft.com/en-us/library/ms680395(v=vs.85).aspx
+    """
+    _fields = [("Length", "u32"),
+               ("Buffer", "u08", lambda string:string.Length),
+    ]
+
+class Module(CStruct):
+    """MINIDUMP_MODULE
+    https://msdn.microsoft.com/en-us/library/ms680392(v=vs.85).aspx
+    """
+    _fields = [("BaseOfImage", "u64"),
+               ("SizeOfImage", "u32"),
+               ("CheckSum", "u32"),
+               ("TimeDateStamp", "u32"),
+               ("ModuleNameRva", "Rva"),
+               ("VersionInfo", "FixedFileInfo"),
+               ("CvRecord", "LocationDescriptor"),
+               ("MiscRecord", "LocationDescriptor"),
+               ("Reserved0", "u64"),
+               ("Reserved1", "u64"),
+    ]
+
+
+class ModuleList(CStruct):
+    """MINIDUMP_MODULE_LIST
+    https://msdn.microsoft.com/en-us/library/ms680391(v=vs.85).aspx
+    """
+    _fields = [("NumberOfModules", "u32"),
+               ("Modules", "Module", lambda mlist:mlist.NumberOfModules),
+    ]
+
+
+class MemoryDescriptor64(CStruct):
+    """MINIDUMP_MEMORY_DESCRIPTOR64
+    https://msdn.microsoft.com/en-us/library/ms680384(v=vs.85).aspx
+    """
+    _fields = [("StartOfMemoryRange", "u64"),
+               ("DataSize", "u64")
+    ]
+
+
+class Memory64List(CStruct):
+    """MINIDUMP_MEMORY64_LIST
+    https://msdn.microsoft.com/en-us/library/ms680387(v=vs.85).aspx
+    """
+    _fields = [("NumberOfMemoryRanges", "u64"),
+               ("BaseRva", "u64"),
+               ("MemoryRanges", "MemoryDescriptor64",
+                lambda mlist:mlist.NumberOfMemoryRanges),
+    ]
+
+class MemoryDescriptor(CStruct):
+    """MINIDUMP_MEMORY_DESCRIPTOR
+    https://msdn.microsoft.com/en-us/library/ms680384(v=vs.85).aspx
+    """
+    _fields = [("StartOfMemoryRange", "u64"),
+               ("Memory", "LocationDescriptor"),
+    ]
+
+class MemoryList(CStruct):
+    """MINIDUMP_MEMORY_LIST
+    https://msdn.microsoft.com/en-us/library/ms680387(v=vs.85).aspx
+    """
+    _fields = [("NumberOfMemoryRanges", "u32"),
+               ("MemoryRanges", "MemoryDescriptor",
+                lambda mlist:mlist.NumberOfMemoryRanges),
+    ]
+
+memProtect = Enumeration({
+    # MEM PROTECT
+    # https://msdn.microsoft.com/en-us/library/aa366786(v=vs.85).aspx
+    "PAGE_NOACCESS"          : 0x0001,
+    "PAGE_READONLY"          : 0x0002,
+    "PAGE_READWRITE"         : 0x0004,
+    "PAGE_WRITECOPY"         : 0x0008,
+    "PAGE_EXECUTE"           : 0x0010,
+    "PAGE_EXECUTE_READ"      : 0x0020,
+    "PAGE_EXECUTE_READWRITE" : 0x0040,
+    "PAGE_EXECUTE_WRITECOPY" : 0x0080,
+    "PAGE_GUARD"             : 0x0100,
+    "PAGE_NOCACHE"           : 0x0200,
+    "PAGE_WRITECOMBINE"      : 0x0400,
+})
+
+class MemoryInfo(CStruct):
+    """MINIDUMP_MEMORY_INFO
+    https://msdn.microsoft.com/en-us/library/ms680386(v=vs.85).aspx
+    """
+    _fields = [("BaseAddress", "u64"),
+               ("AllocationBase", "u64"),
+               ("AllocationProtect", "u32"),
+               ("__alignment1", "u32"),
+               ("RegionSize", "u64"),
+               ("State", "u32"),
+               ("Protect", "u32"),
+               ("Type", "u32"),
+               ("__alignment2", "u32"),
+    ]
+
+class MemoryInfoList(CStruct):
+    """MINIDUMP_MEMORY_INFO_LIST
+    https://msdn.microsoft.com/en-us/library/ms680385(v=vs.85).aspx
+    """
+    _fields = [("SizeOfHeader", "u32"),
+               ("SizeOfEntry", "u32"),
+               ("NumberOfEntries", "u64"),
+                # Fake field, for easy access to MemoryInfo elements
+               ("MemoryInfos", "MemoryInfo",
+                lambda mlist: mlist.NumberOfEntries),
+    ]
+
+
+contextFlags_x86 = Enumeration({
+    "CONTEXT_i386"                : 0x00010000,
+    "CONTEXT_CONTROL"             : 0x00010001,
+    "CONTEXT_INTEGER"             : 0x00010002,
+    "CONTEXT_SEGMENTS"            : 0x00010004,
+    "CONTEXT_FLOATING_POINT"      : 0x00010008,
+    "CONTEXT_DEBUG_REGISTERS"     : 0x00010010,
+    "CONTEXT_EXTENDED_REGISTERS"  : 0x00010020,
+})
+
+class FloatingSaveArea(CStruct):
+    """FLOATING_SAVE_AREA
+    http://terminus.rewolf.pl/terminus/structures/ntdll/_FLOATING_SAVE_AREA_x86.html
+    """
+    _fields = [("ControlWord", "u32"),
+               ("StatusWord", "u32"),
+               ("TagWord", "u32"),
+               ("ErrorOffset", "u32"),
+               ("ErrorSelector", "u32"),
+               ("DataOffset", "u32"),
+               ("DataSelector", "u32"),
+               ("RegisterArea", "80s"),
+               ("Cr0NpxState", "u32"),
+    ]
+
+class Context_x86(CStruct):
+    """CONTEXT x86
+    https://msdn.microsoft.com/en-us/en-en/library/ms679284(v=vs.85).aspx
+    http://terminus.rewolf.pl/terminus/structures/ntdll/_CONTEXT_x86.html
+    """
+
+    MAXIMUM_SUPPORTED_EXTENSION = 512
+
+    def is_activated(flag):
+        mask = contextFlags_x86[flag]
+        def check_context(ctx):
+            if (ctx.ContextFlags & mask == mask):
+                return 1
+            return 0
+        return check_context
+
+    _fields = [("ContextFlags", "u32"),
+               # DebugRegisters
+               ("Dr0", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+               ("Dr1", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+               ("Dr2", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+               ("Dr3", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+               ("Dr6", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+               ("Dr7", "u32", is_activated("CONTEXT_DEBUG_REGISTERS")),
+
+               ("FloatSave", "FloatingSaveArea",
+                is_activated("CONTEXT_FLOATING_POINT")),
+
+               # SegmentRegisters
+               ("SegGs", "u32", is_activated("CONTEXT_SEGMENTS")),
+               ("SegFs", "u32", is_activated("CONTEXT_SEGMENTS")),
+               ("SegEs", "u32", is_activated("CONTEXT_SEGMENTS")),
+               ("SegDs", "u32", is_activated("CONTEXT_SEGMENTS")),
+               # IntegerRegisters
+               ("Edi", "u32", is_activated("CONTEXT_INTEGER")),
+               ("Esi", "u32", is_activated("CONTEXT_INTEGER")),
+               ("Ebx", "u32", is_activated("CONTEXT_INTEGER")),
+               ("Edx", "u32", is_activated("CONTEXT_INTEGER")),
+               ("Ecx", "u32", is_activated("CONTEXT_INTEGER")),
+               ("Eax", "u32", is_activated("CONTEXT_INTEGER")),
+               # ControlRegisters
+               ("Ebp", "u32", is_activated("CONTEXT_CONTROL")),
+               ("Eip", "u32", is_activated("CONTEXT_CONTROL")),
+               ("SegCs", "u32", is_activated("CONTEXT_CONTROL")),
+               ("EFlags", "u32", is_activated("CONTEXT_CONTROL")),
+               ("Esp", "u32", is_activated("CONTEXT_CONTROL")),
+               ("SegSs", "u32", is_activated("CONTEXT_CONTROL")),
+
+               ("ExtendedRegisters", "%ds" % MAXIMUM_SUPPORTED_EXTENSION,
+                is_activated("CONTEXT_EXTENDED_REGISTERS")),
+    ]
+
+
+contextFlags_AMD64 = Enumeration({
+    "CONTEXT_AMD64"               : 0x00100000,
+    "CONTEXT_CONTROL"             : 0x00100001,
+    "CONTEXT_INTEGER"             : 0x00100002,
+    "CONTEXT_SEGMENTS"            : 0x00100004,
+    "CONTEXT_FLOATING_POINT"      : 0x00100008,
+    "CONTEXT_DEBUG_REGISTERS"     : 0x00100010,
+    "CONTEXT_XSTATE"              : 0x00100020,
+    "CONTEXT_EXCEPTION_ACTIVE"    : 0x08000000,
+    "CONTEXT_SERVICE_ACTIVE"      : 0x10000000,
+    "CONTEXT_EXCEPTION_REQUEST"   : 0x40000000,
+    "CONTEXT_EXCEPTION_REPORTING" : 0x80000000,
+})
+
+
+class M128A(CStruct):
+    """M128A
+    http://terminus.rewolf.pl/terminus/structures/ntdll/_M128A_x64.html
+    """
+    _fields = [("Low", "u64"),
+               ("High", "u64"),
+    ]
+
+class Context_AMD64(CStruct):
+    """CONTEXT AMD64
+    https://github.com/duarten/Threadjack/blob/master/WinNT.h
+    """
+
+    def is_activated(flag):
+        mask = contextFlags_AMD64[flag]
+        def check_context(ctx):
+            if (ctx.ContextFlags & mask == mask):
+                return 1
+            return 0
+        return check_context
+
+    _fields = [
+
+        # Only used for Convenience
+        ("P1Home", "u64"),
+        ("P2Home", "u64"),
+        ("P3Home", "u64"),
+        ("P4Home", "u64"),
+        ("P5Home", "u64"),
+        ("P6Home", "u64"),
+
+        # Control
+        ("ContextFlags", "u32"),
+        ("MxCsr", "u32"),
+
+        # Segment & processor
+        # /!\ activation depends on multiple flags
+        ("SegCs", "u16", is_activated("CONTEXT_CONTROL")),
+        ("SegDs", "u16", is_activated("CONTEXT_SEGMENTS")),
+        ("SegEs", "u16", is_activated("CONTEXT_SEGMENTS")),
+        ("SegFs", "u16", is_activated("CONTEXT_SEGMENTS")),
+        ("SegGs", "u16", is_activated("CONTEXT_SEGMENTS")),
+        ("SegSs", "u16", is_activated("CONTEXT_CONTROL")),
+        ("EFlags", "u32", is_activated("CONTEXT_CONTROL")),
+
+        # Debug registers
+        ("Dr0", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+        ("Dr1", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+        ("Dr2", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+        ("Dr3", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+        ("Dr6", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+        ("Dr7", "u64", is_activated("CONTEXT_DEBUG_REGISTERS")),
+
+        # Integer registers
+        # /!\ activation depends on multiple flags
+        ("Rax", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rcx", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rdx", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rbx", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rsp", "u64", is_activated("CONTEXT_CONTROL")),
+        ("Rbp", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rsi", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rdi", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R8", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R9", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R10", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R11", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R12", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R13", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R14", "u64", is_activated("CONTEXT_INTEGER")),
+        ("R15", "u64", is_activated("CONTEXT_INTEGER")),
+        ("Rip", "u64", is_activated("CONTEXT_CONTROL")),
+
+        # Floating point
+        ("Header", "M128A", lambda ctx: 2),
+        ("Legacy", "M128A", lambda ctx: 8),
+        ("Xmm0", "M128A"),
+        ("Xmm1", "M128A"),
+        ("Xmm2", "M128A"),
+        ("Xmm3", "M128A"),
+        ("Xmm4", "M128A"),
+        ("Xmm5", "M128A"),
+        ("Xmm6", "M128A"),
+        ("Xmm7", "M128A"),
+        ("Xmm8", "M128A"),
+        ("Xmm9", "M128A"),
+        ("Xmm10", "M128A"),
+        ("Xmm11", "M128A"),
+        ("Xmm12", "M128A"),
+        ("Xmm13", "M128A"),
+        ("Xmm14", "M128A"),
+        ("Xmm15", "M128A"),
+
+
+        # Vector registers
+        ("VectorRegister", "M128A", lambda ctx: 16),
+        ("VectorControl", "u64"),
+
+        # Special debug control regs
+        ("DebugControl", "u64"),
+        ("LastBranchToRip", "u64"),
+        ("LastBranchFromRip", "u64"),
+        ("LastExceptionToRip", "u64"),
+        ("LastExceptionFromRip", "u64"),
+    ]
+
+processorArchitecture = Enumeration({
+    "PROCESSOR_ARCHITECTURE_X86"       :  0,
+    "PROCESSOR_ARCHITECTURE_MIPS"      :  1,
+    "PROCESSOR_ARCHITECTURE_ALPHA"     :  2,
+    "PROCESSOR_ARCHITECTURE_PPC"       :  3,
+    "PROCESSOR_ARCHITECTURE_SHX"       :  4,
+    "PROCESSOR_ARCHITECTURE_ARM"       :  5,
+    "PROCESSOR_ARCHITECTURE_IA64"      :  6,
+    "PROCESSOR_ARCHITECTURE_ALPHA64"   :  7,
+    "PROCESSOR_ARCHITECTURE_MSIL"      :  8,
+    "PROCESSOR_ARCHITECTURE_AMD64"     :  9,
+    "PROCESSOR_ARCHITECTURE_X86_WIN64" : 10,
+    "PROCESSOR_ARCHITECTURE_UNKNOWN"   : 0xffff,
+})
+
+class Thread(CStruct):
+    """MINIDUMP_THREAD
+    https://msdn.microsoft.com/en-us/library/ms680517(v=vs.85).aspx
+    """
+
+    arch2context_cls = {
+        processorArchitecture.PROCESSOR_ARCHITECTURE_X86: Context_x86,
+        processorArchitecture.PROCESSOR_ARCHITECTURE_AMD64: Context_AMD64,
+    }
+
+    def parse_context(self, content, offset):
+        loc_desc = LocationDescriptor.unpack(content, offset, self.parent_head)
+
+        # Use the correct context depending on architecture
+        systeminfo = self.parent_head.systeminfo
+        context_cls = self.arch2context_cls.get(systeminfo.ProcessorArchitecture,
+                                                None)
+        if context_cls is None:
+            raise ValueError("Unsupported architecture: %s" % systeminfo.pretty_processor_architecture)
+
+        ctxt = context_cls.unpack(content, loc_desc.Rva.rva, self.parent_head)
+        fake_loc_descriptor = LocationDescriptor(DataSize=0, Rva=Rva(rva=0))
+        return ctxt, offset + len(fake_loc_descriptor)
+
+    _fields = [("ThreadId", "u32"),
+               ("SuspendCount", "u32"),
+               ("PriorityClass", "u32"),
+               ("Priority", "u32"),
+               ("Teb", "u64"),
+               ("Stack", "MemoryDescriptor"),
+               ("ThreadContext", (parse_context,
+                                  lambda thread, value: NotImplemented)),
+    ]
+
+class ThreadList(CStruct):
+    """MINIDUMP_THREAD_LIST
+    https://msdn.microsoft.com/en-us/library/ms680515(v=vs.85).aspx
+    """
+    _fields = [("NumberOfThreads", "u32"),
+               ("Threads", "Thread",
+                lambda mlist: mlist.NumberOfThreads),
+    ]
+
+
+class SystemInfo(CStruct):
+    """MINIDUMP_SYSTEM_INFO
+    https://msdn.microsoft.com/en-us/library/ms680396(v=vs.85).aspx
+    """
+    _fields = [("ProcessorArchitecture", "u16"),
+               ("ProcessorLevel", "u16"),
+               ("ProcessorRevision", "u16"),
+               ("NumberOfProcessors", "u08"),
+               ("ProductType", "u08"),
+               ("MajorVersion", "u32"),
+               ("MinorVersion", "u32"),
+               ("BuildNumber", "u32"),
+               ("PlatformId", "u32"),
+               ("CSDVersionRva", "Rva"),
+               ("SuiteMask", "u16"),
+               ("Reserved2", "u16"),
+               ("VendorId", "u32", lambda sinfo: 3),
+               ("VersionInformation", "u32"),
+               ("FeatureInformation", "u32"),
+               ("AMDExtendedCpuFeatures", "u32"),
+    ]
+
+    @property
+    def pretty_processor_architecture(self):
+        return processorArchitecture[self.ProcessorArchitecture]
+
diff --git a/miasm/elfesteem/minidump_init.py b/miasm/elfesteem/minidump_init.py
new file mode 100644
index 00000000..0a9022b9
--- /dev/null
+++ b/miasm/elfesteem/minidump_init.py
@@ -0,0 +1,194 @@
+"""
+High-level abstraction of Minidump file
+"""
+from builtins import range
+import struct
+
+from miasm.elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem import minidump as mp
+
+
+class MemorySegment(object):
+    """Stand for a segment in memory with additional information"""
+
+    def __init__(self, offset, memory_desc, module=None, memory_info=None):
+        self.offset = offset
+        self.memory_desc = memory_desc
+        self.module = module
+        self.memory_info = memory_info
+        self.minidump = self.memory_desc.parent_head
+
+    @property
+    def address(self):
+        return self.memory_desc.StartOfMemoryRange
+
+    @property
+    def size(self):
+        if isinstance(self.memory_desc, mp.MemoryDescriptor64):
+            return self.memory_desc.DataSize
+        elif isinstance(self.memory_desc, mp.MemoryDescriptor):
+            return self.memory_desc.Memory.DataSize
+        raise TypeError
+
+    @property
+    def name(self):
+        if not self.module:
+            return ""
+        name = mp.MinidumpString.unpack(self.minidump._content,
+                                        self.module.ModuleNameRva.rva,
+                                        self.minidump)
+        return b"".join(
+            struct.pack("B", x) for x in name.Buffer
+        ).decode("utf-16")
+
+    @property
+    def content(self):
+        return self.minidump._content[self.offset:self.offset + self.size]
+
+    @property
+    def protect(self):
+        if self.memory_info:
+            return self.memory_info.Protect
+        return None
+
+    @property
+    def pretty_protect(self):
+        if self.protect is None:
+            return "UNKNOWN"
+        return mp.memProtect[self.protect]
+
+
+class Minidump(object):
+    """Stand for a Minidump file
+
+    Here is a few limitation:
+     - only < 4GB Minidump are supported (LocationDescriptor handling)
+     - only Stream relative to memory mapping are implemented
+
+    Official description is available on MSDN:
+    https://msdn.microsoft.com/en-us/library/ms680378(VS.85).aspx
+    """
+
+    _sex = 0
+    _wsize = 32
+
+    def __init__(self, minidump_str):
+        self._content = StrPatchwork(minidump_str)
+
+        # Specific streams
+        self.modulelist = None
+        self.memory64list = None
+        self.memorylist = None
+        self.memoryinfolist = None
+        self.systeminfo = None
+
+        # Get information
+        self.streams = []
+        self.threads = None
+        self.parse_content()
+
+        # Memory information
+        self.memory = {} # base address (virtual) -> Memory information
+        self.build_memory()
+
+    def parse_content(self):
+        """Build structures corresponding to current content"""
+
+        # Header
+        offset = 0
+        self.minidumpHDR = mp.MinidumpHDR.unpack(self._content, offset, self)
+        assert self.minidumpHDR.Magic == 0x504d444d
+
+        # Streams
+        base_offset = self.minidumpHDR.StreamDirectoryRva.rva
+        empty_stream = mp.StreamDirectory(
+            StreamType=0,
+            Location=mp.LocationDescriptor(
+                DataSize=0,
+                Rva=mp.Rva(rva=0)
+            )
+        )
+        streamdir_size = len(empty_stream)
+        for i in range(self.minidumpHDR.NumberOfStreams):
+            stream_offset = base_offset + i * streamdir_size
+            stream = mp.StreamDirectory.unpack(self._content, stream_offset, self)
+            self.streams.append(stream)
+
+            # Launch specific action depending on the stream
+            datasize = stream.Location.DataSize
+            offset = stream.Location.Rva.rva
+            if stream.StreamType == mp.streamType.ModuleListStream:
+                self.modulelist = mp.ModuleList.unpack(self._content, offset, self)
+            elif stream.StreamType == mp.streamType.MemoryListStream:
+                self.memorylist = mp.MemoryList.unpack(self._content, offset, self)
+            elif stream.StreamType == mp.streamType.Memory64ListStream:
+                self.memory64list = mp.Memory64List.unpack(self._content, offset, self)
+            elif stream.StreamType == mp.streamType.MemoryInfoListStream:
+                self.memoryinfolist = mp.MemoryInfoList.unpack(self._content, offset, self)
+            elif stream.StreamType == mp.streamType.SystemInfoStream:
+                self.systeminfo = mp.SystemInfo.unpack(self._content, offset, self)
+
+        # Some streams need the SystemInfo stream to work
+        for stream in self.streams:
+            datasize = stream.Location.DataSize
+            offset = stream.Location.Rva.rva
+            if (self.systeminfo is not None and
+                stream.StreamType == mp.streamType.ThreadListStream):
+                self.threads = mp.ThreadList.unpack(self._content, offset, self)
+
+
+    def build_memory(self):
+        """Build an easier to use memory view based on ModuleList and
+        Memory64List streams"""
+
+        addr2module = dict((module.BaseOfImage, module)
+                           for module in (self.modulelist.Modules if
+                                          self.modulelist else []))
+        addr2meminfo = dict((memory.BaseAddress, memory)
+                            for memory in (self.memoryinfolist.MemoryInfos if
+                                           self.memoryinfolist else []))
+
+        mode64 = self.minidumpHDR.Flags & mp.minidumpType.MiniDumpWithFullMemory
+
+        if mode64:
+            offset = self.memory64list.BaseRva
+            memranges = self.memory64list.MemoryRanges
+        else:
+            memranges = self.memorylist.MemoryRanges
+
+        for memory in memranges:
+            if not mode64:
+                offset = memory.Memory.Rva.rva
+
+            # Create a MemorySegment with augmented information
+            base_address = memory.StartOfMemoryRange
+            module = addr2module.get(base_address, None)
+            meminfo = addr2meminfo.get(base_address, None)
+            self.memory[base_address] = MemorySegment(offset, memory,
+                                                      module, meminfo)
+
+            if mode64:
+                offset += memory.DataSize
+
+        # Sanity check
+        if mode64:
+            assert all(addr in self.memory for addr in addr2module)
+
+    def get(self, virt_start, virt_stop):
+        """Return the content at the (virtual addresses)
+        [virt_start:virt_stop]"""
+
+        # Find the corresponding memory segment
+        for addr in self.memory:
+            if virt_start <= addr <= virt_stop:
+                break
+        else:
+            return b""
+
+        memory = self.memory[addr]
+        shift = addr - virt_start
+        last = virt_stop - addr
+        if last > memory.size:
+            raise RuntimeError("Multi-page not implemented")
+
+        return self._content[memory.offset + shift:memory.offset + last]
diff --git a/miasm/elfesteem/new_cstruct.py b/miasm/elfesteem/new_cstruct.py
new file mode 100644
index 00000000..ec591aa8
--- /dev/null
+++ b/miasm/elfesteem/new_cstruct.py
@@ -0,0 +1,265 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+import re
+import struct
+
+from future.utils import PY3, viewitems, with_metaclass
+
+type2realtype = {}
+size2type = {}
+size2type_s = {}
+
+for t in 'B', 'H', 'I', 'Q':
+    s = struct.calcsize(t)
+    type2realtype[t] = s * 8
+    size2type[s * 8] = t
+
+for t in 'b', 'h', 'i', 'q':
+    s = struct.calcsize(t)
+    type2realtype[t] = s * 8
+    size2type_s[s * 8] = t
+
+type2realtype['u08'] = size2type[8]
+type2realtype['u16'] = size2type[16]
+type2realtype['u32'] = size2type[32]
+type2realtype['u64'] = size2type[64]
+
+type2realtype['s08'] = size2type_s[8]
+type2realtype['s16'] = size2type_s[16]
+type2realtype['s32'] = size2type_s[32]
+type2realtype['s64'] = size2type_s[64]
+
+type2realtype['d'] = 'd'
+type2realtype['f'] = 'f'
+type2realtype['q'] = 'q'
+type2realtype['ptr'] = 'ptr'
+
+sex_types = {0: '<', 1: '>'}
+
+
+def fix_size(fields, wsize):
+    out = []
+    for name, v in fields:
+        if v.endswith("s"):
+            pass
+        elif v == "ptr":
+            v = size2type[wsize]
+        elif not v in type2realtype:
+            raise ValueError("unknown Cstruct type", v)
+        else:
+            v = type2realtype[v]
+        out.append((name, v))
+    fields = out
+    return fields
+
+
+def real_fmt(fmt, wsize):
+    if fmt == "ptr":
+        v = size2type[wsize]
+    elif fmt in type2realtype:
+        v = type2realtype[fmt]
+    else:
+        v = fmt
+    return v
+
+all_cstructs = {}
+
+
+class Cstruct_Metaclass(type):
+    field_suffix = "_value"
+
+    def __new__(cls, name, bases, dct):
+        for fields in dct['_fields']:
+            fname = fields[0]
+            if fname in ['parent', 'parent_head']:
+                raise ValueError('field name will confuse internal structs',
+                                 repr(fname))
+            dct[fname] = property(dct.pop("get_" + fname,
+                                          lambda self, fname=fname: getattr(
+                                              self, fname + self.__class__.field_suffix)),
+                                  dct.pop("set_" + fname,
+                                          lambda self, v, fname=fname: setattr(
+                                              self, fname + self.__class__.field_suffix, v)),
+                                  dct.pop("del_" + fname, None))
+
+        o = super(Cstruct_Metaclass, cls).__new__(cls, name, bases, dct)
+        if name != "CStruct":
+            all_cstructs[name] = o
+        return o
+
+    def unpack_l(cls, s, off=0, parent_head=None, _sex=None, _wsize=None):
+        if _sex is None and _wsize is None:
+            # get sex and size from parent
+            if parent_head is not None:
+                _sex = parent_head._sex
+                _wsize = parent_head._wsize
+            else:
+                _sex = 0
+                _wsize = 32
+        c = cls(_sex=_sex, _wsize=_wsize)
+        if parent_head is None:
+            parent_head = c
+        c.parent_head = parent_head
+
+        of1 = off
+        for field in c._fields:
+            cpt = None
+            if len(field) == 2:
+                fname, ffmt = field
+            elif len(field) == 3:
+                fname, ffmt, cpt = field
+            if ffmt in type2realtype or (isinstance(ffmt, str) and re.match(r'\d+s', ffmt)):
+                # basic types
+                if cpt:
+                    value = []
+                    i = 0
+                    while i < cpt(c):
+                        fmt = real_fmt(ffmt, _wsize)
+                        of2 = of1 + struct.calcsize(fmt)
+                        value.append(struct.unpack(c.sex + fmt, s[of1:of2])[0])
+                        of1 = of2
+                        i += 1
+                else:
+                    fmt = real_fmt(ffmt, _wsize)
+                    of2 = of1 + struct.calcsize(fmt)
+                    if not (0 <= of1 < len(s) and 0 <= of2 < len(s)):
+                        raise RuntimeError("not enough data")
+                    value = struct.unpack(c.sex + fmt, s[of1:of2])[0]
+            elif ffmt == "sz":  # null terminated special case
+                of2 = s.find(b'\x00', of1)
+                if of2 == -1:
+                    raise ValueError('no null char in string!')
+                of2 += 1
+                value = s[of1:of2 - 1]
+            elif ffmt in all_cstructs:
+                of2 = of1
+                # sub structures
+                if cpt:
+                    value = []
+                    i = 0
+                    while i < cpt(c):
+                        v, l = all_cstructs[ffmt].unpack_l(
+                            s, of1, parent_head, _sex, _wsize)
+                        v.parent = c
+                        value.append(v)
+                        of2 = of1 + l
+                        of1 = of2
+                        i += 1
+                else:
+                    value, l = all_cstructs[ffmt].unpack_l(
+                        s, of1, parent_head, _sex, _wsize)
+                    value.parent = c
+                    of2 = of1 + l
+            elif isinstance(ffmt, tuple):
+                f_get, f_set = ffmt
+                value, of2 = f_get(c, s, of1)
+            else:
+                raise ValueError('unknown class', ffmt)
+            of1 = of2
+            setattr(c, fname + c.__class__.field_suffix, value)
+
+        return c, of2 - off
+
+    def unpack(cls, s, off=0, parent_head=None, _sex=None, _wsize=None):
+        c, l = cls.unpack_l(s, off=off,
+                            parent_head=parent_head, _sex=_sex, _wsize=_wsize)
+        return c
+
+
+class CStruct(with_metaclass(Cstruct_Metaclass, object)):
+    _packformat = ""
+    _fields = []
+
+    def __init__(self, parent_head=None, _sex=None, _wsize=None, **kargs):
+        self.parent_head = parent_head
+        self._size = None
+        kargs = dict(kargs)
+        # if not sex or size: get the one of the parent
+        if _sex == None and _wsize == None:
+            if parent_head:
+                _sex = parent_head._sex
+                _wsize = parent_head._wsize
+            else:
+                # else default sex & size
+                _sex = 0
+                _wsize = 32
+        # _sex is 0 or 1, sex is '<' or '>'
+        self._sex = _sex
+        self._wsize = _wsize
+        if self._packformat:
+            self.sex = self._packformat
+        else:
+            self.sex = sex_types[_sex]
+        for f in self._fields:
+            setattr(self, f[0] + self.__class__.field_suffix, None)
+        if kargs:
+            for k, v in viewitems(kargs):
+                self.__dict__[k + self.__class__.field_suffix] = v
+
+    def pack(self):
+        out = b''
+        for field in self._fields:
+            cpt = None
+            if len(field) == 2:
+                fname, ffmt = field
+            elif len(field) == 3:
+                fname, ffmt, cpt = field
+
+            value = getattr(self, fname + self.__class__.field_suffix)
+            if ffmt in type2realtype or (isinstance(ffmt, str) and re.match(r'\d+s', ffmt)):
+                # basic types
+                fmt = real_fmt(ffmt, self._wsize)
+                if cpt == None:
+                    if value == None:
+                        o = struct.calcsize(fmt) * b"\x00"
+                    else:
+                        if isinstance(value, str):
+                            value = value.encode()
+                        o = struct.pack(self.sex + fmt, value)
+                else:
+                    o = b""
+                    for v in value:
+                        if value == None:
+                            o += struct.calcsize(fmt) * b"\x00"
+                        else:
+                            o += struct.pack(self.sex + fmt, v)
+
+            elif ffmt == "sz":  # null terminated special case
+                o = value + b'\x00'
+            elif ffmt in all_cstructs:
+                # sub structures
+                if cpt == None:
+                    o = bytes(value)
+                else:
+                    o = b""
+                    for v in value:
+                        o += bytes(v)
+            elif isinstance(ffmt, tuple):
+                f_get, f_set = ffmt
+                o = f_set(self, value)
+
+            else:
+                raise ValueError('unknown class', ffmt)
+            out += o
+
+        return out
+
+    def __bytes__(self):
+        return self.pack()
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __len__(self):
+        return len(self.pack())
+
+    def __repr__(self):
+        return "<%s=%s>" % (self.__class__.__name__, "/".join(
+            repr(getattr(self, x[0])) for x in self._fields)
+        )
+
+    def __getitem__(self, item):  # to work with format strings
+        return getattr(self, item)
diff --git a/miasm/elfesteem/pe.py b/miasm/elfesteem/pe.py
new file mode 100644
index 00000000..56bffbaa
--- /dev/null
+++ b/miasm/elfesteem/pe.py
@@ -0,0 +1,1668 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+from builtins import range, str
+from collections import defaultdict
+import logging
+import struct
+
+from future.builtins import int as int_types
+from future.utils import PY3
+
+from miasm.core.utils import force_bytes
+from miasm.elfesteem.new_cstruct import CStruct
+from miasm.elfesteem.strpatchwork import StrPatchwork
+
+log = logging.getLogger("pepy")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARN)
+
+
+class InvalidOffset(Exception):
+    pass
+
+
+class Doshdr(CStruct):
+    _fields = [("magic", "u16"),
+               ("cblp", "u16"),
+               ("cp", "u16"),
+               ("crlc", "u16"),
+               ("cparhdr", "u16"),
+               ("minalloc", "u16"),
+               ("maxalloc", "u16"),
+               ("ss", "u16"),
+               ("sp", "u16"),
+               ("csum", "u16"),
+               ("ip", "u16"),
+               ("cs", "u16"),
+               ("lfarlc", "u16"),
+               ("ovno", "u16"),
+               ("res", "8s"),
+               ("oemid", "u16"),
+               ("oeminfo", "u16"),
+               ("res2", "20s"),
+               ("lfanew", "u32")]
+
+
+class NTsig(CStruct):
+    _fields = [("signature", "u32"),
+               ]
+
+
+class Coffhdr(CStruct):
+    _fields = [("machine", "u16"),
+               ("numberofsections", "u16"),
+               ("timedatestamp", "u32"),
+               ("pointertosymboltable", "u32"),
+               ("numberofsymbols", "u32"),
+               ("sizeofoptionalheader", "u16"),
+               ("characteristics", "u16")]
+
+
+class Optehdr(CStruct):
+    _fields = [("rva", "u32"),
+               ("size", "u32")]
+
+
+def get_optehdr_num(nthdr):
+    numberofrva = nthdr.numberofrvaandsizes
+    parent = nthdr.parent_head
+    entry_size = 8
+    if parent.Coffhdr.sizeofoptionalheader < numberofrva * entry_size + len(parent.Opthdr):
+        numberofrva = (parent.Coffhdr.sizeofoptionalheader - len(parent.Opthdr)) // entry_size
+        log.warn('Bad number of rva.. using default %d' % numberofrva)
+        numberofrva = 0x10
+    return numberofrva
+
+
+class Opthdr32(CStruct):
+    _fields = [("magic", "u16"),
+               ("majorlinkerversion", "u08"),
+               ("minorlinkerversion", "u08"),
+               ("SizeOfCode", "u32"),
+               ("sizeofinitializeddata", "u32"),
+               ("sizeofuninitializeddata", "u32"),
+               ("AddressOfEntryPoint", "u32"),
+               ("BaseOfCode", "u32"),
+               ("BaseOfData", "u32"),
+               ]
+
+
+class Opthdr64(CStruct):
+    _fields = [("magic", "u16"),
+               ("majorlinkerversion", "u08"),
+               ("minorlinkerversion", "u08"),
+               ("SizeOfCode", "u32"),
+               ("sizeofinitializeddata", "u32"),
+               ("sizeofuninitializeddata", "u32"),
+               ("AddressOfEntryPoint", "u32"),
+               ("BaseOfCode", "u32"),
+               ]
+
+
+class NThdr(CStruct):
+    _fields = [("ImageBase", "ptr"),
+               ("sectionalignment", "u32"),
+               ("filealignment", "u32"),
+               ("majoroperatingsystemversion", "u16"),
+               ("minoroperatingsystemversion", "u16"),
+               ("MajorImageVersion", "u16"),
+               ("MinorImageVersion", "u16"),
+               ("majorsubsystemversion", "u16"),
+               ("minorsubsystemversion", "u16"),
+               ("Reserved1", "u32"),
+               ("sizeofimage", "u32"),
+               ("sizeofheaders", "u32"),
+               ("CheckSum", "u32"),
+               ("subsystem", "u16"),
+               ("dllcharacteristics", "u16"),
+               ("sizeofstackreserve", "ptr"),
+               ("sizeofstackcommit", "ptr"),
+               ("sizeofheapreserve", "ptr"),
+               ("sizeofheapcommit", "ptr"),
+               ("loaderflags", "u32"),
+               ("numberofrvaandsizes", "u32"),
+               ("optentries", "Optehdr", lambda c:get_optehdr_num(c))
+               ]
+
+
+class Shdr(CStruct):
+    _fields = [("name", "8s"),
+               ("size", "u32"),
+               ("addr", "u32"),
+               ("rawsize", "u32"),
+               ("offset", "u32"),
+               ("pointertorelocations", "u32"),
+               ("pointertolinenumbers", "u32"),
+               ("numberofrelocations", "u16"),
+               ("numberoflinenumbers", "u16"),
+               ("flags", "u32")]
+
+
+    def get_data(self):
+        parent = self.parent_head
+        data = parent.img_rva[self.addr:self.addr + self.size]
+        return data
+
+    def set_data(self, data):
+        parent = self.parent_head
+        parent.img_rva[self.addr] = data
+
+
+    data = property(get_data, set_data)
+
+class SHList(CStruct):
+    _fields = [
+        ("shlist", "Shdr", lambda c:c.parent_head.Coffhdr.numberofsections)]
+
+    def add_section(self, name="default", data=b"", **args):
+        s_align = self.parent_head.NThdr.sectionalignment
+        s_align = max(0x1000, s_align)
+
+        f_align = self.parent_head.NThdr.filealignment
+        f_align = max(0x200, f_align)
+        size = len(data)
+        rawsize = len(data)
+        if len(self):
+            addr = self[-1].addr + self[-1].size
+            s_last = self[0]
+            for section in self:
+                if s_last.offset + s_last.rawsize < section.offset + section.rawsize:
+                    s_last = section
+            offset = s_last.offset + s_last.rawsize
+        else:
+            s_null = bytes(Shdr.unpack(b"\x00" * 0x100))
+            offset = self.parent_head.Doshdr.lfanew + len(self.parent_head.NTsig) + len(
+                self.parent_head.Coffhdr) + self.parent_head.Coffhdr.sizeofoptionalheader + len(bytes(self.parent_head.SHList) + s_null)
+            addr = 0x2000
+        # round addr
+        addr = (addr + (s_align - 1)) & ~(s_align - 1)
+        offset = (offset + (f_align - 1)) & ~(f_align - 1)
+
+        attrs = {"name": name, "size": size,
+                 "addr": addr, "rawsize": rawsize,
+                 "offset": offset,
+                 "pointertorelocations": 0,
+                 "pointertolinenumbers": 0,
+                 "numberofrelocations": 0,
+                 "numberoflinenumbers": 0,
+                 "flags": 0xE0000020,
+                 "data": data
+        }
+        attrs.update(args)
+        section = Shdr(self.parent_head, _sex=self.parent_head._sex,
+                 _wsize=self.parent_head._wsize, **attrs)
+        section.data = data
+
+        if section.rawsize > len(data):
+            section.data = section.data + b'\x00' * (section.rawsize - len(data))
+            section.size = section.rawsize
+        section.data = bytes(StrPatchwork(section.data))
+        section.size = max(s_align, section.size)
+
+        self.append(section)
+        self.parent_head.Coffhdr.numberofsections = len(self)
+
+        length = (section.addr + section.size + (s_align - 1)) & ~(s_align - 1)
+        self.parent_head.NThdr.sizeofimage = length
+        return section
+
+    def align_sections(self, f_align=None, s_align=None):
+        if f_align == None:
+            f_align = self.parent_head.NThdr.filealignment
+            f_align = max(0x200, f_align)
+        if s_align == None:
+            s_align = self.parent_head.NThdr.sectionalignment
+            s_align = max(0x1000, s_align)
+
+        if self is None:
+            return
+
+        addr = self[0].offset
+        for section in self:
+            raw_off = f_align * ((addr + f_align - 1) // f_align)
+            section.offset = raw_off
+            section.rawsize = len(section.data)
+            addr = raw_off + section.rawsize
+
+    def __repr__(self):
+        rep = ["#  section         offset   size   addr     flags   rawsize  "]
+        for i, section in enumerate(self):
+            name = force_bytes(section.name)
+            out = "%-15s" % name.strip(b'\x00').decode()
+            out += "%(offset)08x %(size)06x %(addr)08x %(flags)08x %(rawsize)08x" % section
+            out = ("%2i " % i) + out
+            rep.append(out)
+        return "\n".join(rep)
+
+    def __getitem__(self, item):
+        return self.shlist[item]
+
+    def __len__(self):
+        return len(self.shlist)
+
+    def append(self, section):
+        self.shlist.append(section)
+
+
+class Rva(CStruct):
+    _fields = [("rva", "ptr"),
+               ]
+
+
+class Rva32(CStruct):
+    _fields = [("rva", "u32"),
+               ]
+
+
+class DescName(CStruct):
+    _fields = [("name", (lambda c, raw, off: c.gets(raw, off),
+                         lambda c, value: c.sets(value)))
+               ]
+
+    def gets(self, raw, off):
+        name = raw[off:raw.find(b'\x00', off)]
+        return name, off + len(name) + 1
+
+    def sets(self, value):
+        return bytes(value) + b"\x00"
+
+
+class ImportByName(CStruct):
+    _fields = [("hint", "u16"),
+               ("name", "sz")
+               ]
+
+
+class ImpDesc_e(CStruct):
+    _fields = [("originalfirstthunk", "u32"),
+               ("timestamp", "u32"),
+               ("forwarderchain", "u32"),
+               ("name", "u32"),
+               ("firstthunk", "u32")
+               ]
+
+
+class struct_array(object):
+
+    def __init__(self, target_class, raw, off, cstr, num=None):
+        self.l = []
+        self.cls = target_class
+        self.end = None
+        i = 0
+        if not raw:
+            return
+
+        while (num == None) or (num and i < num):
+            entry, length = cstr.unpack_l(raw, off,
+                                          target_class.parent_head,
+                                          target_class.parent_head._sex,
+                                          target_class.parent_head._wsize)
+            if num == None:
+                if raw[off:off + length] == b'\x00' * length:
+                    self.end = b'\x00' * length
+                    break
+            self.l.append(entry)
+            off += length
+            i += 1
+
+    def __bytes__(self):
+        out = b"".join(bytes(x) for x in self.l)
+        if self.end is not None:
+            out += self.end
+        return out
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __getitem__(self, item):
+        return self.l.__getitem__(item)
+
+    def __len__(self):
+        return len(self.l)
+
+    def append(self, entry):
+        self.l.append(entry)
+
+    def insert(self, index, entry):
+        self.l.insert(index, entry)
+
+
+class DirImport(CStruct):
+    _fields = [("impdesc", (lambda c, raw, off:c.gete(raw, off),
+                            lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        if not off:
+            return None, off
+        if self.parent_head._wsize == 32:
+            mask_ptr = 0x80000000
+        elif self.parent_head._wsize == 64:
+            mask_ptr = 0x8000000000000000
+
+        ofend = off + \
+                self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_IMPORT].size
+        out = []
+        while off < ofend:
+            if not 0 <= off < len(self.parent_head.img_rva):
+                break
+            imp, length = ImpDesc_e.unpack_l(raw, off)
+            if (raw[off:off+length] == b'\x00' * length or
+                imp.name == 0):
+                # Special case
+                break
+            if not (imp.originalfirstthunk or imp.firstthunk):
+                log.warning("no thunk!!")
+                break
+
+            out.append(imp)
+            off += length
+            imp.dlldescname = DescName.unpack(raw, imp.name, self.parent_head)
+            if imp.originalfirstthunk and imp.originalfirstthunk < len(self.parent_head.img_rva):
+                imp.originalfirstthunks = struct_array(self, raw,
+                                                       imp.originalfirstthunk,
+                                                       Rva)
+            else:
+                imp.originalfirstthunks = None
+
+            if imp.firstthunk and imp.firstthunk  < len(self.parent_head.img_rva):
+                imp.firstthunks = struct_array(self, raw,
+                                               imp.firstthunk,
+                                               Rva)
+            else:
+                imp.firstthunks = None
+            imp.impbynames = []
+            if imp.originalfirstthunk and imp.originalfirstthunk < len(self.parent_head.img_rva):
+                tmp_thunk = imp.originalfirstthunks
+            elif imp.firstthunk:
+                tmp_thunk = imp.firstthunks
+            for i in range(len(tmp_thunk)):
+                if tmp_thunk[i].rva & mask_ptr == 0:
+                    try:
+                        entry = ImportByName.unpack(raw,
+                                                    tmp_thunk[i].rva,
+                                                    self.parent_head)
+                    except:
+                        log.warning(
+                            'cannot import from add %s' % tmp_thunk[i].rva
+                        )
+                        entry = 0
+                    imp.impbynames.append(entry)
+                else:
+                    imp.impbynames.append(tmp_thunk[i].rva & (mask_ptr - 1))
+        return out, off
+
+    def sete(self, entries):
+        return b"".join(bytes(entry) for entry in entries) + b"\x00" * (4 * 5)
+
+    def __len__(self):
+        length = (len(self.impdesc) + 1) * (5 * 4)  # ImpDesc_e size
+        rva_size = self.parent_head._wsize // 8
+        for entry in self.impdesc:
+            length += len(entry.dlldescname)
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                length += (len(entry.originalfirstthunks) + 1) * rva_size
+            if entry.firstthunk:
+                length += (len(entry.firstthunks) + 1) * rva_size
+            for imp in entry.impbynames:
+                if isinstance(imp, ImportByName):
+                    length += len(imp)
+        return length
+
+    def set_rva(self, rva, size=None):
+        self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_IMPORT].rva = rva
+        rva_size = self.parent_head._wsize // 8
+        if not size:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_IMPORT].size = len(self)
+        else:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_IMPORT].size = size
+        rva += (len(self.impdesc) + 1) * 5 * 4  # ImpDesc size
+        for entry in self.impdesc:
+            entry.name = rva
+            rva += len(entry.dlldescname)
+            if entry.originalfirstthunk:  # and self.parent_head.rva2off(entry.originalfirstthunk):
+                entry.originalfirstthunk = rva
+                rva += (len(entry.originalfirstthunks) + 1) * rva_size
+            # XXX rva fthunk not patched => keep original func addr
+            # if entry.firstthunk:
+            #    entry.firstthunk = rva
+            # rva+=(len(entry.firstthunks)+1)*self.parent_head._wsize//8 # Rva size
+            if entry.originalfirstthunk and entry.firstthunk:
+                if isinstance(entry.originalfirstthunk, struct_array):
+                    tmp_thunk = entry.originalfirstthunks
+                elif isinstance(entry.firstthunks, struct_array):
+                    tmp_thunk = entry.firstthunks
+                else:
+                    raise RuntimeError("No thunk!")
+            elif entry.originalfirstthunk:  # and self.parent_head.rva2off(entry.originalfirstthunk):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+
+            if tmp_thunk == entry.originalfirstthunks:
+                entry.firstthunks = tmp_thunk
+            else:
+                entry.originalfirstthunks = tmp_thunk
+            for i, imp in enumerate(entry.impbynames):
+                if isinstance(imp, ImportByName):
+                    tmp_thunk[i].rva = rva
+                    rva += len(imp)
+
+    def build_content(self, raw):
+        dirimp = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_IMPORT]
+        of1 = dirimp.rva
+        if not of1:  # No Import
+            return
+        raw[self.parent_head.rva2off(of1)] = bytes(self)
+        for entry in self.impdesc:
+            raw[self.parent_head.rva2off(entry.name)] = bytes(entry.dlldescname)
+            if (entry.originalfirstthunk and
+                self.parent_head.rva2off(entry.originalfirstthunk)):
+                # Add thunks list and terminating null entry
+                off = self.parent_head.rva2off(entry.originalfirstthunk)
+                raw[off] = bytes(entry.originalfirstthunks)
+            if entry.firstthunk:
+                # Add thunks list and terminating null entry
+                off = self.parent_head.rva2off(entry.firstthunk)
+                raw[off] = bytes(entry.firstthunks)
+            if (entry.originalfirstthunk and
+                self.parent_head.rva2off(entry.originalfirstthunk)):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+            for j, imp in enumerate(entry.impbynames):
+                if isinstance(imp, ImportByName):
+                    raw[self.parent_head.rva2off(tmp_thunk[j].rva)] = bytes(imp)
+
+    def get_dlldesc(self):
+        out = []
+        for impdesc in self.impdesc:
+            dllname = impdesc.dlldescname.name
+            funcs = []
+            for imp in impdesc.impbynames:
+                if isinstance(imp, ImportByName):
+                    funcs.append(imp.name)
+                else:
+                    funcs.append(imp)
+            entry = ({"name": dllname, "firstthunk": impdesc.firstthunk}, funcs)
+            out.append(entry)
+        return out
+
+    def __repr__(self):
+        rep = ["<%s>" % self.__class__.__name__]
+        for i, entry in enumerate(self.impdesc):
+            out = "%2d %-25s %s" % (i, repr(entry.dlldescname), repr(entry))
+            rep.append(out)
+            for index, imp in enumerate(entry.impbynames):
+                out = "    %2d %-16s" % (index, repr(imp))
+                rep.append(out)
+        return "\n".join(rep)
+
+    def add_dlldesc(self, new_dll):
+        rva_size = self.parent_head._wsize // 8
+        if self.parent_head._wsize == 32:
+            mask_ptr = 0x80000000
+        elif self.parent_head._wsize == 64:
+            mask_ptr = 0x8000000000000000
+        new_impdesc = []
+        of1 = None
+        for import_descriptor, new_functions in new_dll:
+            if isinstance(import_descriptor.get("name"), str):
+                import_descriptor["name"] = import_descriptor["name"].encode()
+            new_functions = [
+                funcname.encode() if isinstance(funcname, str) else funcname
+                for funcname in new_functions
+            ]
+            for attr in ["timestamp", "forwarderchain", "originalfirstthunk"]:
+                if attr not in import_descriptor:
+                    import_descriptor[attr] = 0
+            entry = ImpDesc_e(self.parent_head, **import_descriptor)
+            if entry.firstthunk != None:
+                of1 = entry.firstthunk
+            elif of1 == None:
+                raise RuntimeError("set fthunk")
+            else:
+                entry.firstthunk = of1
+            entry.dlldescname = DescName(self.parent_head, name=entry.name)
+            entry.originalfirstthunk = 0
+            entry.originalfirstthunks = struct_array(self, None,
+                                                     None,
+                                                     Rva)
+            entry.firstthunks = struct_array(self, None,
+                                             None,
+                                             Rva)
+
+            impbynames = []
+            for new_function in new_functions:
+                rva_ofirstt = Rva(self.parent_head)
+                if isinstance(new_function, int_types):
+                    rva_ofirstt.rva = mask_ptr + new_function
+                    ibn = new_function
+                elif isinstance(new_function, bytes):
+                    rva_ofirstt.rva = True
+                    ibn = ImportByName(self.parent_head)
+                    ibn.name = new_function
+                    ibn.hint = 0
+                else:
+                    raise RuntimeError('unknown func type %s' % new_function)
+                impbynames.append(ibn)
+                entry.originalfirstthunks.append(rva_ofirstt)
+                rva_func = Rva(self.parent_head)
+                if isinstance(ibn, ImportByName):
+                    rva_func.rva = 0xDEADBEEF  # default func addr
+                else:
+                    # ord ?XXX?
+                    rva_func.rva = rva_ofirstt.rva
+                entry.firstthunks.append(rva_func)
+                of1 += rva_size
+            # for null thunk
+            of1 += rva_size
+            entry.impbynames = impbynames
+            new_impdesc.append(entry)
+        if self.impdesc is None:
+            self.impdesc = struct_array(self, None,
+                                        None,
+                                        ImpDesc_e)
+            self.impdesc.l = new_impdesc
+        else:
+            for entry in new_impdesc:
+                self.impdesc.append(entry)
+
+    def get_funcrva(self, dllname, funcname):
+        dllname = force_bytes(dllname)
+        funcname = force_bytes(funcname)
+
+        rva_size = self.parent_head._wsize // 8
+        if self.parent_head._wsize == 32:
+            mask_ptr = 0x80000000 - 1
+        elif self.parent_head._wsize == 64:
+            mask_ptr = 0x8000000000000000 - 1
+
+        for entry in self.impdesc:
+            if entry.dlldescname.name.lower() != dllname.lower():
+                continue
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+            if isinstance(funcname, bytes):
+                for j, imp in enumerate(entry.impbynames):
+                    if isinstance(imp, ImportByName):
+                        if funcname == imp.name:
+                            return entry.firstthunk + j * rva_size
+            elif isinstance(funcname, int_types):
+                for j, imp in enumerate(entry.impbynames):
+                    if not isinstance(imp, ImportByName):
+                        if tmp_thunk[j].rva & mask_ptr == funcname:
+                            return entry.firstthunk + j * rva_size
+            else:
+                raise ValueError('Unknown: %s %s' % (dllname, funcname))
+
+    def get_funcvirt(self, dllname, funcname):
+        rva = self.get_funcrva(dllname, funcname)
+        if rva == None:
+            return
+        return self.parent_head.rva2virt(rva)
+
+
+class ExpDesc_e(CStruct):
+    _fields = [("characteristics", "u32"),
+               ("timestamp", "u32"),
+               ("majorv", "u16"),
+               ("minorv", "u16"),
+               ("name", "u32"),
+               ("base", "u32"),
+               ("numberoffunctions", "u32"),
+               ("numberofnames", "u32"),
+               ("addressoffunctions", "u32"),
+               ("addressofnames", "u32"),
+               ("addressofordinals", "u32"),
+               ]
+
+
+class DirExport(CStruct):
+    _fields = [("expdesc", (lambda c, raw, off:c.gete(raw, off),
+                            lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        off_o = off
+        if not off:
+            return None, off
+        off_sav = off
+        if off >= len(raw):
+            log.warn("export dir malformed!")
+            return None, off_o
+        expdesc = ExpDesc_e.unpack(raw,
+                                   off,
+                                   self.parent_head)
+        if self.parent_head.rva2off(expdesc.addressoffunctions) == None or \
+                self.parent_head.rva2off(expdesc.addressofnames) == None or \
+                self.parent_head.rva2off(expdesc.addressofordinals) == None:
+            log.warn("export dir malformed!")
+            return None, off_o
+        self.dlldescname = DescName.unpack(raw, expdesc.name, self.parent_head)
+        try:
+            self.f_address = struct_array(self, raw,
+                                          expdesc.addressoffunctions,
+                                          Rva32, expdesc.numberoffunctions)
+            self.f_names = struct_array(self, raw,
+                                        expdesc.addressofnames,
+                                        Rva32, expdesc.numberofnames)
+            self.f_nameordinals = struct_array(self, raw,
+                                               expdesc.addressofordinals,
+                                               Ordinal, expdesc.numberofnames)
+        except RuntimeError:
+            log.warn("export dir malformed!")
+            return None, off_o
+        for func in self.f_names:
+            func.name = DescName.unpack(raw, func.rva, self.parent_head)
+        return expdesc, off_sav
+
+    def sete(self, _):
+        return bytes(self.expdesc)
+
+    def build_content(self, raw):
+        direxp = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_EXPORT]
+        of1 = direxp.rva
+        if self.expdesc is None:  # No Export
+            return
+        raw[self.parent_head.rva2off(of1)] = bytes(self.expdesc)
+        raw[self.parent_head.rva2off(self.expdesc.name)] = bytes(self.dlldescname)
+        raw[self.parent_head.rva2off(self.expdesc.addressoffunctions)] = bytes(self.f_address)
+        if self.expdesc.addressofnames != 0:
+            raw[self.parent_head.rva2off(self.expdesc.addressofnames)] = bytes(self.f_names)
+        if self.expdesc.addressofordinals != 0:
+            raw[self.parent_head.rva2off(self.expdesc.addressofordinals)] = bytes(self.f_nameordinals)
+        for func in self.f_names:
+            raw[self.parent_head.rva2off(func.rva)] = bytes(func.name)
+
+        # XXX BUG names must be alphanumeric ordered
+        names = [func.name for func in self.f_names]
+        names_ = names[:]
+        if names != names_:
+            log.warn("unsorted export names, may bug")
+
+    def set_rva(self, rva, size=None):
+        rva_size = self.parent_head._wsize // 8
+        if self.expdesc is None:
+            return
+        self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_EXPORT].rva = rva
+        if not size:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_EXPORT].size = len(self)
+        else:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_EXPORT].size = size
+        rva += len(self.expdesc)
+        self.expdesc.name = rva
+        rva += len(self.dlldescname)
+        self.expdesc.addressoffunctions = rva
+        rva += len(self.f_address) * rva_size
+        self.expdesc.addressofnames = rva
+        rva += len(self.f_names) * rva_size
+        self.expdesc.addressofordinals = rva
+        rva += len(self.f_nameordinals) * 2  # Ordinal size
+        for func in self.f_names:
+            func.rva = rva
+            rva += len(func.name)
+
+    def __len__(self):
+        rva_size = self.parent_head._wsize // 8
+        length = 0
+        if self.expdesc is None:
+            return length
+        length += len(self.expdesc)
+        length += len(self.dlldescname)
+        length += len(self.f_address) * rva_size
+        length += len(self.f_names) * rva_size
+        length += len(self.f_nameordinals) * 2  # Ordinal size
+        for entry in self.f_names:
+            length += len(entry.name)
+        return length
+
+    def __repr__(self):
+        rep = ["<%s>" % self.__class__.__name__]
+        if self.expdesc is None:
+            return "\n".join(rep)
+
+        rep = ["<%s %d (%s) %s>" % (self.__class__.__name__,
+                                    self.expdesc.numberoffunctions, self.dlldescname, repr(self.expdesc))]
+        tmp_names = [[] for _ in range(self.expdesc.numberoffunctions)]
+        for i, entry in enumerate(self.f_names):
+            tmp_names[self.f_nameordinals[i].ordinal].append(entry.name)
+        for i, entry in enumerate(self.f_address):
+            tmpn = []
+            if not entry.rva:
+                continue
+            out = "%2d %.8X %s" % (i + self.expdesc.base, entry.rva, repr(tmp_names[i]))
+            rep.append(out)
+        return "\n".join(rep)
+
+    def create(self, name='default.dll'):
+        self.expdesc = ExpDesc_e(self.parent_head)
+        for attr in ["characteristics",
+                     "timestamp",
+                     "majorv",
+                     "minorv",
+                     "name",
+                     "base",
+                     "numberoffunctions",
+                     "numberofnames",
+                     "addressoffunctions",
+                     "addressofnames",
+                     "addressofordinals",
+                     ]:
+            setattr(self.expdesc, attr, 0)
+
+        self.dlldescname = DescName(self.parent_head)
+        self.dlldescname.name = name
+        self.f_address = struct_array(self, None,
+                                      None,
+                                      Rva)
+        self.f_names = struct_array(self, None,
+                                    None,
+                                    Rva)
+        self.f_nameordinals = struct_array(self, None,
+                                           None,
+                                           Ordinal)
+        self.expdesc.base = 1
+
+    def add_name(self, name, rva=0xdeadc0fe):
+        if self.expdesc is None:
+            return
+        names = [func.name.name for func in self.f_names]
+        names_s = names[:]
+        names_s.sort()
+        if names_s != names:
+            log.warn('tab names was not sorted may bug')
+        names.append(name)
+        names.sort()
+        index = names.index(name)
+        descname = DescName(self.parent_head)
+
+        descname.name = name
+        wname = Rva(self.parent_head)
+
+        wname.name = descname
+        woffset = Rva(self.parent_head)
+        woffset.rva = rva
+        wordinal = Ordinal(self.parent_head)
+        # func is append to list
+        wordinal.ordinal = len(self.f_address)
+        self.f_address.append(woffset)
+        # self.f_names.insert(index, wname)
+        # self.f_nameordinals.insert(index, wordinal)
+        self.f_names.insert(index, wname)
+        self.f_nameordinals.insert(index, wordinal)
+        self.expdesc.numberofnames += 1
+        self.expdesc.numberoffunctions += 1
+
+    def get_funcrva(self, f_str):
+        if self.expdesc is None:
+            return None
+        for i, entry in enumerate(self.f_names):
+            if f_str != entry.name.name:
+                continue
+            ordinal = self.f_nameordinals[i].ordinal
+            rva = self.f_address[ordinal].rva
+            return rva
+        return None
+
+    def get_funcvirt(self, addr):
+        rva = self.get_funcrva(addr)
+        if rva == None:
+            return
+        return self.parent_head.rva2virt(rva)
+
+
+class Delaydesc_e(CStruct):
+    _fields = [("attrs", "u32"),
+               ("name", "u32"),
+               ("hmod", "u32"),
+               ("firstthunk", "u32"),
+               ("originalfirstthunk", "u32"),
+               ("boundiat", "u32"),
+               ("unloadiat", "u32"),
+               ("timestamp", "u32"),
+               ]
+
+
+class DirDelay(CStruct):
+    _fields = [("delaydesc", (lambda c, raw, off:c.gete(raw, off),
+                              lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        if not off:
+            return None, off
+
+        ofend = off + \
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_DELAY_IMPORT].size
+        out = []
+        while off < ofend:
+            if off >= len(raw):
+                log.warn('warning bad reloc offset')
+                break
+
+            delaydesc, length = Delaydesc_e.unpack_l(raw,
+                                                     off,
+                                                     self.parent_head)
+            if raw[off:off+length] == b'\x00' * length:
+                # Special case
+                break
+            off += length
+            out.append(delaydesc)
+
+        if self.parent_head._wsize == 32:
+            mask_ptr = 0x80000000
+        elif self.parent_head._wsize == 64:
+            mask_ptr = 0x8000000000000000
+
+        parent = self.parent_head
+        for entry in out:
+            isfromva = (entry.attrs & 1) == 0
+            if isfromva:
+                isfromva = lambda x: parent.virt2rva(x)
+            else:
+                isfromva = lambda x: x
+            entry.dlldescname = DescName.unpack(raw, isfromva(entry.name),
+                                                self.parent_head)
+            if entry.originalfirstthunk:
+                addr = isfromva(entry.originalfirstthunk)
+                if not 0 <= addr < len(raw):
+                    log.warning("Bad delay")
+                    break
+                entry.originalfirstthunks = struct_array(self, raw,
+                                                         addr,
+                                                         Rva)
+            else:
+                entry.originalfirstthunks
+
+            if entry.firstthunk:
+                entry.firstthunks = struct_array(self, raw,
+                                                 isfromva(entry.firstthunk),
+                                                 Rva)
+            else:
+                entry.firstthunk = None
+
+            entry.impbynames = []
+            if entry.originalfirstthunk and self.parent_head.rva2off(isfromva(entry.originalfirstthunk)):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                print(ValueError("no thunk in delay dir!! "))
+                return
+            for i in range(len(tmp_thunk)):
+                if tmp_thunk[i].rva & mask_ptr == 0:
+                    imp = ImportByName.unpack(raw,
+                                              isfromva(tmp_thunk[i].rva),
+                                              self.parent_head)
+                    entry.impbynames.append(imp)
+                else:
+                    entry.impbynames.append(
+                        isfromva(tmp_thunk[i].rva & (mask_ptr - 1)))
+                    # print(repr(entry[-1]))
+                    # raise ValueError('XXX to check')
+        return out, off
+
+    def sete(self, entries):
+        return "".join(bytes(entry) for entry in entries) + b"\x00" * (4 * 8)  # DelayDesc_e
+
+    def __len__(self):
+        rva_size = self.parent_head._wsize // 8
+        length = (len(self.delaydesc) + 1) * (4 * 8)  # DelayDesc_e
+        for entry in self.delaydesc:
+            length += len(entry.dlldescname)
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                length += (len(entry.originalfirstthunks) + 1) * rva_size
+            if entry.firstthunk:
+                length += (len(entry.firstthunks) + 1) * rva_size
+            for imp in entry.impbynames:
+                if isinstance(imp, ImportByName):
+                    length += len(imp)
+        return length
+
+    def set_rva(self, rva, size=None):
+        rva_size = self.parent_head._wsize // 8
+        self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_DELAY_IMPORT].rva = rva
+        if not size:
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_DELAY_IMPORT].size = len(self)
+        else:
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_DELAY_IMPORT].size = size
+        rva += (len(self.delaydesc) + 1) * (4 * 8)  # DelayDesc_e
+        parent = self.parent_head
+        for entry in self.delaydesc:
+            isfromva = (entry.attrs & 1) == 0
+            if isfromva:
+                isfromva = lambda x: self.parent_head.rva2virt(x)
+            else:
+                isfromva = lambda x: x
+
+            entry.name = isfromva(rva)
+            rva += len(entry.dlldescname)
+            if entry.originalfirstthunk:  # and self.parent_head.rva2off(entry.originalfirstthunk):
+                entry.originalfirstthunk = isfromva(rva)
+                rva += (len(entry.originalfirstthunks) + 1) * rva_size
+            # XXX rva fthunk not patched => fun addr
+            # if entry.firstthunk:
+            #    entry.firstthunk = rva
+            #    rva+=(len(entry.firstthunks)+1)*pe.Rva._size
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+            for i, imp in enumerate(entry.impbynames):
+                if isinstance(imp, ImportByName):
+                    tmp_thunk[i].rva = isfromva(rva)
+                    rva += len(imp)
+
+    def build_content(self, raw):
+        if len(self.parent_head.NThdr.optentries) < DIRECTORY_ENTRY_DELAY_IMPORT:
+            return
+        dirdelay = self.parent_head.NThdr.optentries[
+            DIRECTORY_ENTRY_DELAY_IMPORT]
+        of1 = dirdelay.rva
+        if not of1:  # No Delay Import
+            return
+        raw[self.parent_head.rva2off(of1)] = bytes(self)
+        for entry in self.delaydesc:
+            raw[self.parent_head.rva2off(entry.name)] = bytes(entry.dlldescname)
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                raw[self.parent_head.rva2off(entry.originalfirstthunk)] = bytes(entry.originalfirstthunks)
+            if entry.firstthunk:
+                raw[self.parent_head.rva2off(entry.firstthunk)] = bytes(entry.firstthunks)
+            if entry.originalfirstthunk and self.parent_head.rva2off(entry.originalfirstthunk):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+            for j, imp in enumerate(entry.impbynames):
+                if isinstance(imp, ImportByName):
+                    raw[self.parent_head.rva2off(tmp_thunk[j].rva)] = bytes(imp)
+
+    def __repr__(self):
+        rep = ["<%s>" % self.__class__.__name__]
+        for i, entry in enumerate(self.delaydesc):
+            out = "%2d %-25s %s" % (i, repr(entry.dlldescname), repr(entry))
+            rep.append(out)
+            for index, func in enumerate(entry.impbynames):
+                out = "    %2d %-16s" % (index, repr(func))
+                rep.append(out)
+        return "\n".join(rep)
+
+    def add_dlldesc(self, new_dll):
+        if self.parent_head._wsize == 32:
+            mask_ptr = 0x80000000
+        elif self.parent_head._wsize == 64:
+            mask_ptr = 0x8000000000000000
+        new_impdesc = []
+        of1 = None
+        new_delaydesc = []
+        for import_descriptor, new_functions in new_dll:
+            if isinstance(import_descriptor.get("name"), str):
+                import_descriptor["name"] = import_descriptor["name"].encode()
+            new_functions = [
+                funcname.encode() if isinstance(funcname, str) else funcname
+                for funcname in new_functions
+            ]
+            for attr in ["attrs", "name", "hmod", "firstthunk", "originalfirstthunk", "boundiat", "unloadiat", "timestamp"]:
+                if not attr in import_descriptor:
+                    import_descriptor[attr] = 0
+            entry = Delaydesc_e(self.parent_head, **import_descriptor)
+            # entry.cstr.__dict__.update(import_descriptor)
+            if entry.firstthunk != None:
+                of1 = entry.firstthunk
+            elif of1 == None:
+                raise RuntimeError("set fthunk")
+            else:
+                entry.firstthunk = of1
+            entry.dlldescname = DescName(self.parent_head, name=entry.name)
+            entry.originalfirstthunk = 0
+            entry.originalfirstthunks = struct_array(self, None,
+                                                     None,
+                                                     Rva)
+            entry.firstthunks = struct_array(self, None,
+                                             None,
+                                             Rva)
+
+            impbynames = []
+            for new_function in new_functions:
+                rva_ofirstt = Rva(self.parent_head)
+                if isinstance(new_function, int_types):
+                    rva_ofirstt.rva = mask_ptr + new_function
+                    ibn = None
+                elif isinstance(new_function, bytes):
+                    rva_ofirstt.rva = True
+                    ibn = ImportByName(self.parent_head)
+                    ibn.name = new_function
+                    ibn.hint = 0
+                else:
+                    raise RuntimeError('unknown func type %s' % new_function)
+                impbynames.append(ibn)
+                entry.originalfirstthunks.append(rva_ofirstt)
+
+                rva_func = Rva(self.parent_head)
+                if ibn != None:
+                    rva_func.rva = 0xDEADBEEF  # default func addr
+                else:
+                    # ord ?XXX?
+                    rva_func.rva = rva_ofirstt.rva
+                entry.firstthunks.append(rva_func)
+                of1 += 4
+            # for null thunk
+            of1 += 4
+            entry.impbynames = impbynames
+            new_delaydesc.append(entry)
+        if self.delaydesc is None:
+            self.delaydesc = struct_array(self, None,
+                                          None,
+                                          Delaydesc_e)
+            self.delaydesc.l = new_delaydesc
+        else:
+            for entry in new_delaydesc:
+                self.delaydesc.append(entry)
+
+    def get_funcrva(self, func):
+        for entry in self.delaydesc:
+            isfromva = (entry.attrs & 1) == 0
+            if isfromva:
+                isfromva = lambda x: self.parent_head.virt2rva(x)
+            else:
+                isfromva = lambda x: x
+            if entry.originalfirstthunk and self.parent_head.rva2off(isfromva(entry.originalfirstthunk)):
+                tmp_thunk = entry.originalfirstthunks
+            elif entry.firstthunk:
+                tmp_thunk = entry.firstthunks
+            else:
+                raise RuntimeError("No thunk!")
+            if isinstance(func, bytes):
+                for j, imp in enumerate(entry.impbynames):
+                    if isinstance(imp, ImportByName):
+                        if func == imp.name:
+                            return isfromva(entry.firstthunk) + j * 4
+            elif isinstance(func, int_types):
+                for j, imp in enumerate(entry.impbynames):
+                    if not isinstance(imp, ImportByName):
+                        if isfromva(tmp_thunk[j].rva & 0x7FFFFFFF) == func:
+                            return isfromva(entry.firstthunk) + j * 4
+            else:
+                raise ValueError('unknown func tpye %r' % func)
+
+    def get_funcvirt(self, addr):
+        rva = self.get_funcrva(addr)
+        if rva == None:
+            return
+        return self.parent_head.rva2virt(rva)
+
+
+class Rel(CStruct):
+    _fields = [("rva", "u32"),
+               ("size", "u32")
+               ]
+
+
+class Reloc(CStruct):
+    _fields = [("rel", (lambda c, raw, off:c.gete(raw, off),
+                        lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        rel = struct.unpack('H', raw[off:off + 2])[0]
+        return (rel >> 12, rel & 0xfff), off + 2
+
+    def sete(self, value):
+        return struct.pack('H', (value[0] << 12) | value[1])
+
+    def __repr__(self):
+        return '<%d %d>' % (self.rel[0], self.rel[1])
+
+
+class DirReloc(CStruct):
+    _fields = [("reldesc", (lambda c, raw, off:c.gete(raw, off),
+                            lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        if not off:
+            return None, off
+
+        ofend = off + \
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_BASERELOC].size
+        out = []
+        while off < ofend:
+            if off >= len(raw):
+                log.warn('warning bad reloc offset')
+                break
+            reldesc, length = Rel.unpack_l(raw,
+                                           off,
+                                           self.parent_head)
+            if reldesc.size == 0:
+                log.warn('warning null reldesc')
+                reldesc.size = length
+                break
+            of2 = off + length
+            if of2 + reldesc.size > len(self.parent_head.img_rva):
+                log.warn('relocation too big, skipping')
+                break
+            reldesc.rels = struct_array(self, raw,
+                                        of2,
+                                        Reloc,
+                                        (reldesc.size - length) // 2)  # / Reloc size
+            reldesc.patchrel = False
+            out.append(reldesc)
+            off += reldesc.size
+        return out, off
+
+    def sete(self, entries):
+        return b"".join(
+            bytes(entry) + bytes(entry.rels)
+            for entry in entries
+        )
+
+    def set_rva(self, rva, size=None):
+        if self.reldesc is None:
+            return
+        self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_BASERELOC].rva = rva
+        if not size:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_BASERELOC].size = len(self)
+        else:
+            self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_BASERELOC].size = size
+
+    def build_content(self, raw):
+        dirrel = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_BASERELOC]
+        dirrel.size = len(self)
+        of1 = dirrel.rva
+        if self.reldesc is None:  # No Reloc
+            return
+        raw[self.parent_head.rva2off(of1)] = bytes(self)
+
+    def __len__(self):
+        if self.reldesc is None:
+            return 0
+        length = 0
+        for entry in self.reldesc:
+            length += entry.size
+        return length
+
+    def __bytes__(self):
+        return b"".join(
+            bytes(entry) + bytes(entry.rels)
+            for entry in self.reldesc
+        )
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __repr__(self):
+        rep = ["<%s>" % self.__class__.__name__]
+        if self.reldesc is None:
+            return "\n".join(rep)
+        for i, entry in enumerate(self.reldesc):
+            out = "%2d %s" % (i, repr(entry))
+            rep.append(out)
+            """
+            #display too many lines...
+            for ii, m in enumerate(entry.rels):
+                l = "\t%2d %s"%(ii, repr(m) )
+                rep.append(l)
+            """
+            out = "\t%2d rels..." % (len(entry.rels))
+            rep.append(out)
+        return "\n".join(rep)
+
+    def add_reloc(self, rels, rtype=3, patchrel=True):
+        dirrel = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_BASERELOC]
+        if not rels:
+            return
+        rels.sort()
+        all_base_ad = set([x & 0xFFFFF000 for x in rels])
+        all_base_ad = list(all_base_ad)
+        all_base_ad.sort()
+        rels_by_base = defaultdict(list)
+        while rels:
+            reloc = rels.pop()
+            if reloc >= all_base_ad[-1]:
+                rels_by_base[all_base_ad[-1]].append(reloc)
+            else:
+                all_base_ad.pop()
+                rels_by_base[all_base_ad[-1]].append(reloc)
+        rels_by_base = [x for x in list(rels_by_base.items())]
+        rels_by_base.sort()
+        for o_init, rels in rels_by_base:
+            # o_init = rels[0]&0xFFFFF000
+            offsets = struct_array(self, None, None, Reloc, 0)
+            for reloc_value in rels:
+                if (reloc_value & 0xFFFFF000) != o_init:
+                    raise RuntimeError("relocs must be in same range")
+                reloc = Reloc(self.parent_head)
+                reloc.rel = (rtype, reloc_value - o_init)
+                offsets.append(reloc)
+            while len(offsets) & 3:
+                reloc = Reloc(self.parent_head)
+                reloc.rel = (0, 0)
+                offsets.append(reloc)
+            reldesc = Rel(self.parent_head)  # Reloc(self.parent_head)
+            reldesc.rva = o_init
+            reldesc.size = (len(offsets) * 2 + 8)
+            reldesc.rels = offsets
+            reldesc.patchrel = patchrel
+            # if self.reldesc is None:
+            #    self.reldesc = []
+            self.reldesc.append(reldesc)
+            dirrel.size += reldesc.size
+
+    def del_reloc(self, taboffset):
+        if self.reldesc is None:
+            return
+        for rel in self.reldesc:
+            of1 = rel.rva
+            i = 0
+            while i < len(rel.rels):
+                reloc = rel.rels[i]
+                if reloc.rel[0] != 0 and reloc.rel[1] + of1 in taboffset:
+                    print('del reloc', hex(reloc.rel[1] + of1))
+                    del rel.rels[i]
+                    rel.size -= Reloc._size
+                else:
+                    i += 1
+
+
+class DirRes(CStruct):
+    _fields = [("resdesc", (lambda c, raw, off:c.gete(raw, off),
+                            lambda c, value:c.sete(value)))]
+
+    def gete(self, raw, off):
+        if not off:
+            return None, off
+        if off >= len(self.parent_head.img_rva):
+            log.warning('cannot parse resources, %X' % off)
+            return None, off
+
+        off_orig = off
+        ofend = off + self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].size
+
+        resdesc, length = ResDesc_e.unpack_l(raw,
+                                             off,
+                                             self.parent_head)
+        off += length
+        nbr = resdesc.numberofnamedentries + resdesc.numberofidentries
+
+        out = []
+        tmp_off = off
+        for _ in range(nbr):
+            if tmp_off >= ofend:
+                break
+            if tmp_off + length >= len(raw):
+                log.warn('warning bad resource offset')
+                break
+            try:
+                entry, length = ResEntry.unpack_l(raw, tmp_off, self.parent_head)
+            except RuntimeError:
+                log.warn('bad resentry')
+                return None, tmp_off
+            out.append(entry)
+            tmp_off += length
+        resdesc.resentries = struct_array(self, raw,
+                                          off,
+                                          ResEntry,
+                                          nbr)
+        dir_todo = {off_orig: resdesc}
+        dir_done = {}
+        while dir_todo:
+            off, my_dir = dir_todo.popitem()
+            dir_done[off] = my_dir
+            for entry in my_dir.resentries:
+                off = entry.offsettosubdir
+                if not off:
+                    # data dir
+                    off = entry.offsettodata
+                    if not 0 <= off < len(raw):
+                        log.warn('bad resrouce entry')
+                        continue
+                    data = ResDataEntry.unpack(raw,
+                                               off,
+                                               self.parent_head)
+                    off = data.offsettodata
+                    data.s = StrPatchwork(raw[off:off + data.size])
+                    entry.data = data
+                    continue
+                # subdir
+                if off in dir_done:
+                    log.warn('warning recusif subdir')
+                    continue
+                if not 0 <= off < len(self.parent_head.img_rva):
+                    log.warn('bad resrouce entry')
+                    continue
+                subdir, length = ResDesc_e.unpack_l(raw,
+                                                    off,
+                                                    self.parent_head)
+                nbr = subdir.numberofnamedentries + subdir.numberofidentries
+                try:
+                    subdir.resentries = struct_array(self, raw,
+                                                     off + length,
+                                                     ResEntry,
+                                                     nbr)
+                except RuntimeError:
+                    log.warn('bad resrouce entry')
+                    continue
+
+                entry.subdir = subdir
+                dir_todo[off] = entry.subdir
+        return resdesc, off
+
+    def build_content(self, raw):
+        if self.resdesc is None:
+            return
+        of1 = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].rva
+        raw[self.parent_head.rva2off(of1)] = bytes(self.resdesc)
+        dir_todo = {self.parent_head.NThdr.optentries[
+            DIRECTORY_ENTRY_RESOURCE].rva: self.resdesc}
+        dir_done = {}
+        while dir_todo:
+            of1, my_dir = dir_todo.popitem()
+            dir_done[of1] = my_dir
+            raw[self.parent_head.rva2off(of1)] = bytes(my_dir)
+            of1 += len(my_dir)
+            of_base = of1
+            for entry in my_dir.resentries:
+                raw[of_base] = bytes(entry)
+                of_base += len(entry)
+                if entry.name_s:
+                    raw[self.parent_head.rva2off(entry.name)] = bytes(entry.name_s)
+                of1 = entry.offsettosubdir
+                if not of1:
+                    raw[self.parent_head.rva2off(entry.offsettodata)] = bytes(entry.data)
+                    raw[self.parent_head.rva2off(entry.data.offsettodata)] = bytes(entry.data.s)
+                    continue
+                dir_todo[of1] = entry.subdir
+
+    def __len__(self):
+        length = 0
+        if self.resdesc is None:
+            return length
+        dir_todo = [self.resdesc]
+        dir_done = []
+        while dir_todo:
+            my_dir = dir_todo.pop()
+            if my_dir in dir_done:
+                raise ValueError('Recursive directory')
+            dir_done.append(my_dir)
+            length += len(my_dir)
+            length += len(my_dir.resentries) * 8  # ResEntry size
+            for entry in my_dir.resentries:
+                if not entry.offsettosubdir:
+                    continue
+                if not entry.subdir in dir_todo:
+                    dir_todo.append(entry.subdir)
+                else:
+                    raise RuntimeError("recursive dir")
+
+        dir_todo = dir_done
+        while dir_todo:
+            my_dir = dir_todo.pop()
+            for entry in my_dir.resentries:
+                if entry.name_s:
+                    length += len(entry.name_s)
+                of1 = entry.offsettosubdir
+                if not of1:
+                    length += 4 * 4  # WResDataEntry size
+                    # XXX because rva may be even rounded
+                    length += 1
+                    length += entry.data.size
+                    continue
+        return length
+
+    def set_rva(self, rva, size=None):
+        if self.resdesc is None:
+            return
+        self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].rva = rva
+        if not size:
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].size = len(self)
+        else:
+            self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].size = size
+        dir_todo = [self.resdesc]
+        dir_done = {}
+        while dir_todo:
+            my_dir = dir_todo.pop()
+            dir_done[rva] = my_dir
+            rva += len(my_dir)
+            rva += len(my_dir.resentries) * 8  # ResEntry size
+            for entry in my_dir.resentries:
+                if not entry.offsettosubdir:
+                    continue
+                if not entry.subdir in dir_todo:
+                    dir_todo.append(entry.subdir)
+                else:
+                    raise RuntimeError("recursive dir")
+        dir_todo = dir_done
+        dir_inv = dict([(x[1], x[0]) for x in list(dir_todo.items())])
+        while dir_todo:
+            rva_tmp, my_dir = dir_todo.popitem()
+            for entry in my_dir.resentries:
+                if entry.name_s:
+                    entry.name = rva
+                    rva += len(entry.name_s)
+                of1 = entry.offsettosubdir
+                if not of1:
+                    entry.offsettodata = rva
+                    rva += 4 * 4  # ResDataEntry size
+                    # XXX menu rsrc must be even aligned?
+                    if rva % 2:
+                        rva += 1
+                    entry.data.offsettodata = rva
+                    rva += entry.data.size
+                    continue
+                entry.offsettosubdir = dir_inv[entry.subdir]
+
+    def __repr__(self):
+        rep = ["<%s>" % (self.__class__.__name__)]
+        if self.resdesc is None:
+            return "\n".join(rep)
+        dir_todo = [self.resdesc]
+        resources = []
+        index = -1
+        while dir_todo:
+            entry = dir_todo.pop(0)
+            if isinstance(entry, int):
+                index += entry
+            elif isinstance(entry, ResDesc_e):
+                # resources.append((index, repr(entry)))
+                dir_todo = [1] + entry.resentries.l + [-1] + dir_todo
+            elif isinstance(entry, ResEntry):
+                if entry.offsettosubdir:
+                    resources.append((index, repr(entry)))
+                    dir_todo = [entry.subdir] + dir_todo
+                else:
+                    resources.append((index, repr(entry)))
+            else:
+                raise RuntimeError("zarb")
+        for i, resource in resources:
+            rep.append(' ' * 4 * i + resource)
+        return "\n".join(rep)
+
+
+class Ordinal(CStruct):
+    _fields = [("ordinal", "u16"),
+               ]
+
+
+class ResDesc_e(CStruct):
+    _fields = [("characteristics", "u32"),
+               ("timestamp", "u32"),
+               ("majorv", "u16"),
+               ("minorv", "u16"),
+               ("numberofnamedentries", "u16"),
+               ("numberofidentries", "u16")
+               ]
+
+
+class SUnicode(CStruct):
+    _fields = [("length", "u16"),
+               ("value", (lambda c, raw, off:c.gets(raw, off),
+                          lambda c, value:c.sets(value)))
+               ]
+
+    def gets(self, raw, off):
+        value = raw[off:off + self.length * 2]
+        return value, off + self.length
+
+    def sets(self, value):
+        return self.value
+
+
+class ResEntry(CStruct):
+    _fields = [("name", (lambda c, raw, off:c._get_name(raw, off),
+                         lambda c, value:c._set_name(value))),
+               ("offsettodata", (lambda c, raw, off:c._get_offset(raw, off),
+                                 lambda c, value:c._set_offset(value)))
+               ]
+
+    def _get_name(self, raw, off):
+        self.data = None
+        # off = self.parent_head.rva2off(off)
+        name = struct.unpack('I', raw[off:off + 4])[0]
+        self.name_s = None
+        if name & 0x80000000:
+            name = (name & 0x7FFFFFFF) + self.parent_head.NThdr.optentries[
+                DIRECTORY_ENTRY_RESOURCE].rva  # XXX res rva??
+            name &= 0x7FFFFFFF
+            if name >= len(raw):
+                raise RuntimeError("Bad resentry")
+            self.name_s = SUnicode.unpack(raw,
+                                          name,
+                                          self.parent_head)
+        return name, off + 4
+
+    def _set_name(self, name):
+        if self.name_s:
+            rva = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].rva
+            name = (self.name - rva) + 0x80000000
+        return struct.pack('I', name)
+
+    def _get_offset(self, raw, off):
+        self.offsettosubdir = None
+        rva = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].rva
+        offsettodata_o = struct.unpack('I', raw[off:off + 4])[0]
+        offsettodata = (offsettodata_o & 0x7FFFFFFF) + rva  # XXX res rva??
+        if offsettodata_o & 0x80000000:
+            self.offsettosubdir = offsettodata
+        return offsettodata, off + 4
+
+    def _set_offset(self, offset):
+        rva = self.parent_head.NThdr.optentries[DIRECTORY_ENTRY_RESOURCE].rva
+        offsettodata = offset - rva
+        if self.offsettosubdir:
+            offsettodata = (self.offsettosubdir - rva) + 0x80000000
+        return struct.pack('I', offsettodata)
+
+    def __repr__(self):
+        if self.name_s:
+            nameid = "%s" % repr(self.name_s)
+        else:
+            if self.name in RT:  # and not self.offsettosubdir:
+                nameid = "ID %s" % RT[self.name]
+            else:
+                nameid = "ID %d" % self.name
+        if self.offsettosubdir:
+            offsettodata = "subdir: %x" % self.offsettosubdir
+        else:
+            offsettodata = "data: %x" % self.offsettodata
+        return "<%s %s>" % (nameid, offsettodata)
+
+
+class ResDataEntry(CStruct):
+    _fields = [("offsettodata", "u32"),
+               ("size", "u32"),
+               ("codepage", "u32"),
+               ("reserved", "u32"),
+               ]
+
+
+class Symb(CStruct):
+    _fields = [("name", "8s"),
+               ("res1", "u32"),
+               ("res2", "u32"),
+               ("res3", "u16")]
+
+
+DIRECTORY_ENTRY_EXPORT = 0
+DIRECTORY_ENTRY_IMPORT = 1
+DIRECTORY_ENTRY_RESOURCE = 2
+DIRECTORY_ENTRY_EXCEPTION = 3
+DIRECTORY_ENTRY_SECURITY = 4
+DIRECTORY_ENTRY_BASERELOC = 5
+DIRECTORY_ENTRY_DEBUG = 6
+DIRECTORY_ENTRY_COPYRIGHT = 7
+DIRECTORY_ENTRY_GLOBALPTR = 8
+DIRECTORY_ENTRY_TLS = 9
+DIRECTORY_ENTRY_LOAD_CONFIG = 10
+DIRECTORY_ENTRY_BOUND_IMPORT = 11
+DIRECTORY_ENTRY_IAT = 12
+DIRECTORY_ENTRY_DELAY_IMPORT = 13
+DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
+DIRECTORY_ENTRY_RESERVED = 15
+
+
+RT_CURSOR = 1
+RT_BITMAP = 2
+RT_ICON = 3
+RT_MENU = 4
+RT_DIALOG = 5
+RT_STRING = 6
+RT_FONTDIR = 7
+RT_FONT = 8
+RT_ACCELERATOR = 9
+RT_RCDATA = 10
+RT_MESSAGETABLE = 11
+RT_GROUP_CURSOR = 12
+RT_GROUP_ICON = 14
+RT_VERSION = 16
+RT_DLGINCLUDE = 17
+RT_PLUGPLAY = 19
+RT_VXD = 20
+RT_ANICURSOR = 21
+RT_ANIICON = 22
+RT_HTML = 23
+RT_MANIFEST = 24
+
+
+RT = {
+    RT_CURSOR: "RT_CURSOR",
+    RT_BITMAP: "RT_BITMAP",
+    RT_ICON: "RT_ICON",
+    RT_MENU: "RT_MENU",
+    RT_DIALOG: "RT_DIALOG",
+    RT_STRING: "RT_STRING",
+    RT_FONTDIR: "RT_FONTDIR",
+    RT_FONT: "RT_FONT",
+    RT_ACCELERATOR: "RT_ACCELERATOR",
+    RT_RCDATA: "RT_RCDATA",
+    RT_MESSAGETABLE: "RT_MESSAGETABLE",
+    RT_GROUP_CURSOR: "RT_GROUP_CURSOR",
+    RT_GROUP_ICON: "RT_GROUP_ICON",
+    RT_VERSION: "RT_VERSION",
+    RT_DLGINCLUDE: "RT_DLGINCLUDE",
+    RT_PLUGPLAY: "RT_PLUGPLAY",
+    RT_VXD: "RT_VXD",
+    RT_ANICURSOR: "RT_ANICURSOR",
+    RT_ANIICON: "RT_ANIICON",
+    RT_HTML: "RT_HTML",
+    RT_MANIFEST: "RT_MANIFEST",
+}
diff --git a/miasm/elfesteem/pe_init.py b/miasm/elfesteem/pe_init.py
new file mode 100644
index 00000000..e243cecb
--- /dev/null
+++ b/miasm/elfesteem/pe_init.py
@@ -0,0 +1,603 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+
+from builtins import range
+import array
+from functools import reduce
+import logging
+import struct
+
+from future.builtins import int as int_types
+from future.utils import PY3
+
+from miasm.elfesteem import pe
+from miasm.elfesteem.strpatchwork import StrPatchwork
+
+log = logging.getLogger("peparse")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARN)
+
+
+class ContentManager(object):
+
+    def __get__(self, owner, _):
+        if hasattr(owner, '_content'):
+            return owner._content
+
+    def __set__(self, owner, new_content):
+        owner.resize(len(owner._content), len(new_content))
+        owner._content = new_content
+
+    def __delete__(self, owner):
+        self.__set__(owner, None)
+
+
+class ContectRva(object):
+
+    def __init__(self, parent):
+        self.parent = parent
+
+    def get(self, rva_start, rva_stop=None):
+        """
+        Get data in RVA view starting at @rva_start, stopping at @rva_stop
+        @rva_start: rva start address
+        @rva_stop: rva stop address
+        """
+        if rva_start < 0:
+            raise ValueError("Out of range")
+        if rva_stop is not None:
+            if rva_stop > len(self.parent.img_rva):
+                rva_stop = len(self.parent.img_rva)
+            if rva_start > len(self.parent.img_rva):
+                raise ValueError("Out of range")
+            return self.parent.img_rva[rva_start:rva_stop]
+        if rva_start > len(self.parent.img_rva):
+            raise ValueError("Out of range")
+        return self.parent.img_rva[rva_start]
+
+    def set(self, rva, data):
+        """
+        Set @data in RVA view starting at @start
+        @rva: rva start address
+        @data: data to set
+        """
+        if not isinstance(rva, int_types):
+            raise ValueError('addr must be int/long')
+
+        if rva < 0:
+            raise ValueError("Out of range")
+
+        if rva + len(data) > len(self.parent.img_rva):
+            raise ValueError("Out of range")
+        self.parent.img_rva[rva] = data
+
+    def __getitem__(self, item):
+        if isinstance(item, slice):
+            assert(item.step is None)
+            return self.get(item.start, item.stop)
+        return self.get(item)
+
+    def __setitem__(self, item, data):
+        if isinstance(item, slice):
+            rva = item.start
+        else:
+            rva = item
+        self.set(rva, data)
+
+
+class ContentVirtual(object):
+
+    def __init__(self, parent):
+        self.parent = parent
+
+    def __getitem__(self, item):
+        raise DeprecationWarning("Replace code by virt.get(start, [stop])")
+
+    def __setitem__(self, item, data):
+        raise DeprecationWarning("Replace code by virt.set(start, data)")
+
+    def __call__(self, ad_start, ad_stop=None, ad_step=None):
+        raise DeprecationWarning("Replace code by virt.get(start, stop)")
+
+    def get(self, virt_start, virt_stop=None):
+        """
+        Get data in VIRTUAL view starting at @virt_start, stopping at @virt_stop
+        @virt_start: virt start address
+        @virt_stop: virt stop address
+        """
+        rva_start = self.parent.virt2rva(virt_start)
+        if virt_stop != None:
+            rva_stop = self.parent.virt2rva(virt_stop)
+        else:
+            rva_stop = None
+        return self.parent.rva.get(rva_start, rva_stop)
+
+    def set(self, addr, data):
+        """
+        Set @data in VIRTUAL view starting at @start
+        @addr: virtual start address
+        @data: data to set
+        """
+        if not isinstance(addr, int_types):
+            raise ValueError('addr must be int/long')
+        self.parent.rva.set(self.parent.virt2rva(addr), data)
+
+    def max_addr(self):
+        section = self.parent.SHList[-1]
+        length = section.addr + section.size + self.parent.NThdr.ImageBase
+        return int(length)
+
+    def find(self, pattern, start=0, end=None):
+        if start != 0:
+            start = self.parent.virt2rva(start)
+        if end != None:
+            end = self.parent.virt2rva(end)
+
+        ret = self.parent.img_rva.find(pattern, start, end)
+        if ret == -1:
+            return -1
+        return self.parent.rva2virt(ret)
+
+    def rfind(self, pattern, start=0, end=None):
+        if start != 0:
+            start = self.parent.virt2rva(start)
+        if end != None:
+            end = self.parent.virt2rva(end)
+
+        ret = self.parent.img_rva.rfind(pattern, start, end)
+        if ret == -1:
+            return -1
+        return self.parent.rva2virt(ret)
+
+    def is_addr_in(self, addr):
+        return self.parent.is_in_virt_address(addr)
+
+
+
+def compute_crc(raw, olds):
+    out = 0
+    data = raw[:]
+    if len(raw) % 2:
+        end = struct.unpack('B', data[-1])[0]
+        data = data[:-1]
+    if (len(raw) & ~0x1) % 4:
+        out += struct.unpack('H', data[:2])[0]
+        data = data[2:]
+    data = array.array('I', data)
+    out = reduce(lambda x, y: x + y, data, out)
+    out -= olds
+    while out > 0xFFFFFFFF:
+        out = (out >> 32) + (out & 0xFFFFFFFF)
+    while out > 0xFFFF:
+        out = (out & 0xFFFF) + ((out >> 16) & 0xFFFF)
+    if len(raw) % 2:
+        out += end
+    out += len(data)
+    return out
+
+
+
+# PE object
+class PE(object):
+    content = ContentManager()
+
+    def __init__(self, pestr=None,
+                 loadfrommem=False,
+                 parse_resources=True,
+                 parse_delay=True,
+                 parse_reloc=True,
+                 wsize=32):
+        self._rva = ContectRva(self)
+        self._virt = ContentVirtual(self)
+        self.img_rva = StrPatchwork()
+        if pestr is None:
+            self._content = StrPatchwork()
+            self._sex = 0
+            self._wsize = wsize
+            self.Doshdr = pe.Doshdr(self)
+            self.NTsig = pe.NTsig(self)
+            self.Coffhdr = pe.Coffhdr(self)
+
+            if self._wsize == 32:
+                Opthdr = pe.Opthdr32
+            else:
+                Opthdr = pe.Opthdr64
+
+            self.Opthdr = Opthdr(self)
+            self.NThdr = pe.NThdr(self)
+            self.NThdr.optentries = [pe.Optehdr(self) for _ in range(0x10)]
+            self.NThdr.CheckSum = 0
+            self.SHList = pe.SHList(self)
+            self.SHList.shlist = []
+
+            self.NThdr.sizeofheaders = 0x1000
+
+            self.DirImport = pe.DirImport(self)
+            self.DirExport = pe.DirExport(self)
+            self.DirDelay = pe.DirDelay(self)
+            self.DirReloc = pe.DirReloc(self)
+            self.DirRes = pe.DirRes(self)
+
+            self.Doshdr.magic = 0x5a4d
+            self.Doshdr.lfanew = 0xe0
+
+            self.NTsig.signature = 0x4550
+            if wsize == 32:
+                self.Opthdr.magic = 0x10b
+            elif wsize == 64:
+                self.Opthdr.magic = 0x20b
+            else:
+                raise ValueError('unknown pe size %r' % wsize)
+            self.Opthdr.majorlinkerversion = 0x7
+            self.Opthdr.minorlinkerversion = 0x0
+            self.NThdr.filealignment = 0x1000
+            self.NThdr.sectionalignment = 0x1000
+            self.NThdr.majoroperatingsystemversion = 0x5
+            self.NThdr.minoroperatingsystemversion = 0x1
+            self.NThdr.MajorImageVersion = 0x5
+            self.NThdr.MinorImageVersion = 0x1
+            self.NThdr.majorsubsystemversion = 0x4
+            self.NThdr.minorsubsystemversion = 0x0
+            self.NThdr.subsystem = 0x3
+            if wsize == 32:
+                self.NThdr.dllcharacteristics = 0x8000
+            else:
+                self.NThdr.dllcharacteristics = 0x8000
+
+            # for createthread
+            self.NThdr.sizeofstackreserve = 0x200000
+            self.NThdr.sizeofstackcommit = 0x1000
+            self.NThdr.sizeofheapreserve = 0x100000
+            self.NThdr.sizeofheapcommit = 0x1000
+
+            self.NThdr.ImageBase = 0x400000
+            self.NThdr.sizeofheaders = 0x1000
+            self.NThdr.numberofrvaandsizes = 0x10
+
+            self.NTsig.signature = 0x4550
+            if wsize == 32:
+                self.Coffhdr.machine = 0x14c
+            elif wsize == 64:
+                self.Coffhdr.machine = 0x8664
+            else:
+                raise ValueError('unknown pe size %r' % wsize)
+            if wsize == 32:
+                self.Coffhdr.characteristics = 0x10f
+                self.Coffhdr.sizeofoptionalheader = 0xe0
+            else:
+                self.Coffhdr.characteristics = 0x22  # 0x2f
+                self.Coffhdr.sizeofoptionalheader = 0xf0
+
+        else:
+            self._content = StrPatchwork(pestr)
+            self.loadfrommem = loadfrommem
+            self.parse_content(parse_resources=parse_resources,
+                               parse_delay=parse_delay,
+                               parse_reloc=parse_reloc)
+
+    def isPE(self):
+        if self.NTsig is None:
+            return False
+        return self.NTsig.signature == 0x4550
+
+    def parse_content(self,
+                      parse_resources=True,
+                      parse_delay=True,
+                      parse_reloc=True):
+        off = 0
+        self._sex = 0
+        self._wsize = 32
+        self.Doshdr = pe.Doshdr.unpack(self.content, off, self)
+        off = self.Doshdr.lfanew
+        if off > len(self.content):
+            log.warn('ntsig after eof!')
+            self.NTsig = None
+            return
+        self.NTsig = pe.NTsig.unpack(self.content,
+                                     off, self)
+        self.DirImport = None
+        self.DirExport = None
+        self.DirDelay = None
+        self.DirReloc = None
+        self.DirRes = None
+
+        if self.NTsig.signature != 0x4550:
+            log.warn('not a valid pe!')
+            return
+        off += len(self.NTsig)
+        self.Coffhdr, length = pe.Coffhdr.unpack_l(self.content,
+                                                   off,
+                                                   self)
+
+        off += length
+        self._wsize = ord(self.content[off+1]) * 32
+
+        if self._wsize == 32:
+            Opthdr = pe.Opthdr32
+        else:
+            Opthdr = pe.Opthdr64
+
+        if len(self.content) < 0x200:
+            # Fix for very little PE
+            self.content += (0x200 - len(self.content)) * b'\x00'
+
+        self.Opthdr, length = Opthdr.unpack_l(self.content, off, self)
+        self.NThdr = pe.NThdr.unpack(self.content, off + length, self)
+        self.img_rva[0] = self.content[:self.NThdr.sizeofheaders]
+        off += self.Coffhdr.sizeofoptionalheader
+        self.SHList = pe.SHList.unpack(self.content, off, self)
+
+        # load section data
+        filealignment = self.NThdr.filealignment
+        sectionalignment = self.NThdr.sectionalignment
+        for section in self.SHList.shlist:
+            virt_size = (section.size // sectionalignment + 1) * sectionalignment
+            if self.loadfrommem:
+                section.offset = section.addr
+            if self.NThdr.sectionalignment > 0x1000:
+                raw_off = 0x200 * (section.offset // 0x200)
+            else:
+                raw_off = section.offset
+            if raw_off != section.offset:
+                log.warn('unaligned raw section (%x %x)!', raw_off, section.offset)
+            section.data = StrPatchwork()
+
+            if section.rawsize == 0:
+                rounded_size = 0
+            else:
+                if section.rawsize % filealignment:
+                    rs = (section.rawsize // filealignment + 1) * filealignment
+                else:
+                    rs = section.rawsize
+                rounded_size = rs
+            if rounded_size > virt_size:
+                rounded_size = min(rounded_size, section.size)
+            data = self.content[raw_off:raw_off + rounded_size]
+            section.data = data
+            # Pad data to page size 0x1000
+            length = len(data)
+            data += b"\x00" * ((((length + 0xfff)) & 0xFFFFF000) - length)
+            self.img_rva[section.addr] = data
+        # Fix img_rva
+        self.img_rva = self.img_rva
+
+        try:
+            self.DirImport = pe.DirImport.unpack(self.img_rva,
+                                                 self.NThdr.optentries[
+                                                     pe.DIRECTORY_ENTRY_IMPORT].rva,
+                                                 self)
+        except pe.InvalidOffset:
+            log.warning('cannot parse DirImport, skipping')
+            self.DirImport = pe.DirImport(self)
+
+        try:
+            self.DirExport = pe.DirExport.unpack(self.img_rva,
+                                                 self.NThdr.optentries[
+                                                     pe.DIRECTORY_ENTRY_EXPORT].rva,
+                                                 self)
+        except pe.InvalidOffset:
+            log.warning('cannot parse DirExport, skipping')
+            self.DirExport = pe.DirExport(self)
+
+        if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_DELAY_IMPORT:
+            self.DirDelay = pe.DirDelay(self)
+            if parse_delay:
+                try:
+                    self.DirDelay = pe.DirDelay.unpack(self.img_rva,
+                                                       self.NThdr.optentries[
+                                                           pe.DIRECTORY_ENTRY_DELAY_IMPORT].rva,
+                                                       self)
+                except pe.InvalidOffset:
+                    log.warning('cannot parse DirDelay, skipping')
+        if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_BASERELOC:
+            self.DirReloc = pe.DirReloc(self)
+            if parse_reloc:
+                try:
+                    self.DirReloc = pe.DirReloc.unpack(self.img_rva,
+                                                       self.NThdr.optentries[
+                                                           pe.DIRECTORY_ENTRY_BASERELOC].rva,
+                                                       self)
+                except pe.InvalidOffset:
+                    log.warning('cannot parse DirReloc, skipping')
+        if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_RESOURCE:
+            self.DirRes = pe.DirRes(self)
+            if parse_resources:
+                self.DirRes = pe.DirRes(self)
+                try:
+                    self.DirRes = pe.DirRes.unpack(self.img_rva,
+                                                   self.NThdr.optentries[
+                                                       pe.DIRECTORY_ENTRY_RESOURCE].rva,
+                                                   self)
+                except pe.InvalidOffset:
+                    log.warning('cannot parse DirRes, skipping')
+
+    def resize(self, old, new):
+        pass
+
+    def __getitem__(self, item):
+        return self.content[item]
+
+    def __setitem__(self, item, data):
+        self.content.__setitem__(item, data)
+        return
+
+    def getsectionbyrva(self, rva):
+        if self.SHList is None:
+            return None
+        for section in self.SHList.shlist:
+            """
+            TODO CHECK:
+            some binaries have import rva outside section, but addresses
+            seems to be rounded
+            """
+            mask = self.NThdr.sectionalignment - 1
+            if section.addr <= rva < (section.addr + section.size + mask) & ~(mask):
+                return section
+        return None
+
+    def getsectionbyvad(self, vad):
+        return self.getsectionbyrva(self.virt2rva(vad))
+
+    def getsectionbyoff(self, off):
+        if self.SHList is None:
+            return None
+        for section in self.SHList.shlist:
+            if section.offset <= off < section.offset + section.rawsize:
+                return section
+        return None
+
+    def getsectionbyname(self, name):
+        if self.SHList is None:
+            return None
+        for section in self.SHList:
+            if section.name.strip(b'\x00').decode() == name:
+                return section
+        return None
+
+    def is_rva_ok(self, rva):
+        return self.getsectionbyrva(rva) is not None
+
+    def rva2off(self, rva):
+        # Special case rva in header
+        if rva < self.NThdr.sizeofheaders:
+            return rva
+        section = self.getsectionbyrva(rva)
+        if section is None:
+            raise pe.InvalidOffset('cannot get offset for 0x%X' % rva)
+        soff = (section.offset // self.NThdr.filealignment) * self.NThdr.filealignment
+        return rva - section.addr + soff
+
+    def off2rva(self, off):
+        section = self.getsectionbyoff(off)
+        if section is None:
+            return
+        return off - section.offset + section.addr
+
+    def virt2rva(self, virt):
+        if virt is None:
+            return
+        return virt - self.NThdr.ImageBase
+
+    def rva2virt(self, rva):
+        if rva is None:
+            return
+        return rva + self.NThdr.ImageBase
+
+    def virt2off(self, virt):
+        return self.rva2off(self.virt2rva(virt))
+
+    def off2virt(self, off):
+        return self.rva2virt(self.off2rva(off))
+
+    def is_in_virt_address(self, addr):
+        if addr < self.NThdr.ImageBase:
+            return False
+        addr = self.virt2rva(addr)
+        for section in self.SHList.shlist:
+            if section.addr <= addr < section.addr + section.size:
+                return True
+        return False
+
+    def get_drva(self):
+        print('Deprecated: Use PE.rva instead of PE.drva')
+        return self._rva
+
+    def get_rva(self):
+        return self._rva
+
+    # TODO XXX remove drva api
+    drva = property(get_drva)
+    rva = property(get_rva)
+
+    def get_virt(self):
+        return self._virt
+
+    virt = property(get_virt)
+
+    def build_content(self):
+
+        content = StrPatchwork()
+        content[0] = bytes(self.Doshdr)
+
+        for section in self.SHList.shlist:
+            content[section.offset:section.offset + section.rawsize] = bytes(section.data)
+
+        # fix image size
+        section_last = self.SHList.shlist[-1]
+        size = section_last.addr + section_last.size + (self.NThdr.sectionalignment - 1)
+        size &= ~(self.NThdr.sectionalignment - 1)
+        self.NThdr.sizeofimage = size
+
+        off = self.Doshdr.lfanew
+        content[off] = bytes(self.NTsig)
+        off += len(self.NTsig)
+        content[off] = bytes(self.Coffhdr)
+        off += len(self.Coffhdr)
+        off_shlist = off + self.Coffhdr.sizeofoptionalheader
+        content[off] = bytes(self.Opthdr)
+        off += len(self.Opthdr)
+        content[off] = bytes(self.NThdr)
+        off += len(self.NThdr)
+        # content[off] = bytes(self.Optehdr)
+
+        off = off_shlist
+        content[off] = bytes(self.SHList)
+
+        for section in self.SHList:
+            if off + len(bytes(self.SHList)) > section.offset:
+                log.warn("section offset overlap pe hdr 0x%x 0x%x" %
+                         (off + len(bytes(self.SHList)), section.offset))
+        self.DirImport.build_content(content)
+        self.DirExport.build_content(content)
+        self.DirDelay.build_content(content)
+        self.DirReloc.build_content(content)
+        self.DirRes.build_content(content)
+
+        if (self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr)) % 4:
+            log.warn("non aligned coffhdr, bad crc calculation")
+        crcs = compute_crc(bytes(content), self.NThdr.CheckSum)
+        content[self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr) + 64] = struct.pack('I', crcs)
+        return bytes(content)
+
+    def __bytes__(self):
+        return self.build_content()
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def export_funcs(self):
+        if self.DirExport is None:
+            print('no export dir found')
+            return None, None
+
+        all_func = {}
+        for i, export in enumerate(self.DirExport.f_names):
+            all_func[export.name.name] = self.rva2virt(
+                self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva)
+            all_func[self.DirExport.f_nameordinals[i].ordinal + self.DirExport.expdesc.base] = self.rva2virt(
+                self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva)
+        # XXX todo: test if redirected export
+        return all_func
+
+    def reloc_to(self, imgbase):
+        offset = imgbase - self.NThdr.ImageBase
+        if self.DirReloc is None:
+            log.warn('no relocation found!')
+        for rel in self.DirReloc.reldesc:
+            rva = rel.rva
+            for reloc in rel.rels:
+                reloc_type, off = reloc.rel
+                if reloc_type == 0 and off == 0:
+                    continue
+                if reloc_type != 3:
+                    raise NotImplementedError('Reloc type not supported')
+                off += rva
+                value = struct.unpack('I', self.rva.get(off, off + 4))[0]
+                value += offset
+                self.rva.set(off, struct.pack('I', value & 0xFFFFFFFF))
+        self.NThdr.ImageBase = imgbase
diff --git a/miasm/elfesteem/strpatchwork.py b/miasm/elfesteem/strpatchwork.py
new file mode 100644
index 00000000..e1a5de91
--- /dev/null
+++ b/miasm/elfesteem/strpatchwork.py
@@ -0,0 +1,106 @@
+from array import array
+import struct
+from sys import maxsize
+
+from future.utils import PY3
+
+if PY3:
+
+    def array_frombytes(arr, value):
+        return arr.frombytes(value)
+
+    def array_tobytes(arr):
+        return arr.tobytes()
+
+
+else:
+
+    def array_frombytes(arr, value):
+        return arr.fromstring(value)
+
+    def array_tobytes(arr):
+        return arr.tostring()
+
+
+class StrPatchwork(object):
+
+    def __init__(self, s=b"", paddingbyte=b"\x00"):
+        s_raw = bytes(s)
+        val = array("B")
+        array_frombytes(val, s_raw)
+        self.s = val
+        # cache s to avoid rebuilding str after each find
+        self.s_cache = s_raw
+        self.paddingbyte = paddingbyte
+
+    def __bytes__(self):
+        return array_tobytes(self.s)
+
+    def __str__(self):
+        if PY3:
+            return repr(self)
+        return self.__bytes__()
+
+    def __getitem__(self, item):
+        s = self.s
+        if isinstance(item, slice):
+            end = item.stop
+            l = len(s)
+            if (end is not None and l < end) and end != maxsize:
+                # XXX hack [x:] give 2GB limit
+                # This is inefficient but avoids complicated maths if step is
+                # not 1
+                s = s[:]
+
+                tmp = array("B")
+                array_frombytes(tmp, self.paddingbyte * (end - l))
+                s.extend(tmp)
+            r = s[item]
+            return array_tobytes(r)
+
+        else:
+            if item > len(s):
+                return self.paddingbyte
+            else:
+                return struct.pack("B", s[item])
+
+    def __setitem__(self, item, val):
+        if val is None:
+            return
+        val_array = array("B")
+        array_frombytes(val_array, bytes(val))
+        if type(item) is not slice:
+            item = slice(item, item + len(val_array))
+        end = item.stop
+        l = len(self.s)
+        if l < end:
+            tmp = array("B")
+            array_frombytes(tmp, self.paddingbyte * (end - l))
+            self.s.extend(tmp)
+        self.s[item] = val_array
+        self.s_cache = None
+
+    def __repr__(self):
+        return "<Patchwork %r>" % array_tobytes(self.s)
+
+    def __len__(self):
+        return len(self.s)
+
+    def __contains__(self, val):
+        return val in bytes(self)
+
+    def __iadd__(self, other):
+        tmp = array("B")
+        array_frombytes(tmp, bytes(other))
+        self.s.extend(tmp)
+        return self
+
+    def find(self, pattern, start=0, end=None):
+        if not self.s_cache:
+            self.s_cache = array_tobytes(self.s)
+        return self.s_cache.find(pattern, start, end)
+
+    def rfind(self, pattern, start=0, end=None):
+        if not self.s_cache:
+            self.s_cache = array_tobytes(self.s)
+        return self.s_cache.rfind(pattern, start, end)
diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py
index b36638f3..4c68fc91 100644
--- a/miasm/jitter/loader/elf.py
+++ b/miasm/jitter/loader/elf.py
@@ -3,9 +3,9 @@ from collections import defaultdict
 
 from future.utils import viewitems
 
-from elfesteem import cstruct
-from elfesteem import *
-import elfesteem.elf as elf_csts
+from miasm.elfesteem import cstruct
+from miasm.elfesteem import *
+import miasm.elfesteem.elf as elf_csts
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
@@ -56,11 +56,11 @@ def preload_elf(vm, e, runtime_lib, patch_vm_imp=True, loc_db=None):
     return runtime_lib, dyn_funcs
 
 def fill_loc_db_with_symbols(elf, loc_db, base_addr=0):
-    """Parse the elfesteem's ELF @elf to extract symbols, and fill the LocationDB
+    """Parse the miasm.elfesteem's ELF @elf to extract symbols, and fill the LocationDB
     instance @loc_db with parsed symbols.
 
     The ELF is considered mapped at @base_addr
-    @elf: elfesteem's ELF instance
+    @elf: miasm.elfesteem's ELF instance
     @loc_db: LocationDB used to retrieve symbols'offset
     @base_addr: addr to reloc to (if any)
     """
@@ -163,7 +163,7 @@ def fill_loc_db_with_symbols(elf, loc_db, base_addr=0):
 
 def apply_reloc_x86(elf, vm, section, base_addr, loc_db):
     """Apply relocation for x86 ELF contained in the section @section
-    @elf: elfesteem's ELF instance
+    @elf: miasm.elfesteem's ELF instance
     @vm: VmMngr instance
     @section: elf's section containing relocation to perform
     @base_addr: addr to reloc to
diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py
index 7145a817..a2bdd3ac 100644
--- a/miasm/jitter/loader/pe.py
+++ b/miasm/jitter/loader/pe.py
@@ -6,9 +6,9 @@ from collections import defaultdict
 
 from future.utils import viewitems, viewvalues
 
-from elfesteem import pe
-from elfesteem import cstruct
-from elfesteem import *
+from miasm.elfesteem import pe
+from miasm.elfesteem import cstruct
+from miasm.elfesteem import *
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
diff --git a/miasm/os_dep/win_api_x86_32_seh.py b/miasm/os_dep/win_api_x86_32_seh.py
index 90a68eec..5d8ed3d7 100644
--- a/miasm/os_dep/win_api_x86_32_seh.py
+++ b/miasm/os_dep/win_api_x86_32_seh.py
@@ -23,7 +23,7 @@ import struct
 
 from future.utils import viewitems
 
-from elfesteem import pe_init
+from miasm.elfesteem import pe_init
 
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.core.utils import pck32
diff --git a/requirements.txt b/requirements.txt
index 84530589..135ca071 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,3 @@
 pyparsing
 future
-git+https://github.com/serpilliere/elfesteem@py23_lalet#egg=elfesteem-0.1
 llvmlite==0.26.0
diff --git a/setup.py b/setup.py
index c52e1f9e..3aaeaf27 100755
--- a/setup.py
+++ b/setup.py
@@ -30,6 +30,7 @@ def buil_all():
         "miasm/analysis",
         "miasm/os_dep",
         "miasm/os_dep/linux",
+        "miasm/elfesteem",
         "miasm/jitter",
         "miasm/jitter/arch",
         "miasm/jitter/loader",
diff --git a/test/analysis/dse.py b/test/analysis/dse.py
index 8691551c..21225f54 100644
--- a/test/analysis/dse.py
+++ b/test/analysis/dse.py
@@ -3,7 +3,7 @@ from pdb import pm
 
 from future.utils import viewitems
 
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem.strpatchwork import StrPatchwork
 from miasm.core import parse_asm
 from miasm.expression.expression import ExprCompose, ExprOp, ExprInt, ExprId
 from miasm.core.asmblock import asm_resolve_final
diff --git a/test/arch/aarch64/unit/asm_test.py b/test/arch/aarch64/unit/asm_test.py
index 65a537a0..9d193b47 100644
--- a/test/arch/aarch64/unit/asm_test.py
+++ b/test/arch/aarch64/unit/asm_test.py
@@ -7,7 +7,7 @@ from miasm.arch.aarch64.arch import mn_aarch64, base_expr, variable
 from miasm.core import parse_asm
 from miasm.expression.expression import *
 from miasm.core import asmblock
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem.strpatchwork import StrPatchwork
 from miasm.analysis.machine import Machine
 from miasm.jitter.csts import *
 
diff --git a/test/arch/mips32/unit/asm_test.py b/test/arch/mips32/unit/asm_test.py
index 38a2d928..dd95c3af 100644
--- a/test/arch/mips32/unit/asm_test.py
+++ b/test/arch/mips32/unit/asm_test.py
@@ -7,7 +7,7 @@ from miasm.arch.mips32.arch import mn_mips32
 from miasm.core import parse_asm
 from miasm.expression.expression import *
 from miasm.core import asmblock
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem.strpatchwork import StrPatchwork
 from miasm.analysis.machine import Machine
 from miasm.jitter.csts import *
 
diff --git a/test/arch/x86/unit/asm_test.py b/test/arch/x86/unit/asm_test.py
index 0059f511..cf87ac93 100644
--- a/test/arch/x86/unit/asm_test.py
+++ b/test/arch/x86/unit/asm_test.py
@@ -9,7 +9,7 @@ from miasm.arch.x86.arch import mn_x86, base_expr, variable
 from miasm.core import parse_asm
 from miasm.expression.expression import *
 from miasm.core import asmblock
-from elfesteem.strpatchwork import StrPatchwork
+from miasm.elfesteem.strpatchwork import StrPatchwork
 from miasm.analysis.machine import Machine
 from miasm.jitter.csts import *