Initialize the binary.

        :return: None

def _initialize(self):
        """
        Initialize the binary.

        :return: None
        """

        # figure out section alignments
        for section in self.project.loader.main_object.sections:
            in_segment = False
            for segment in self.project.loader.main_object.segments:
                segment_addr = segment.vaddr
                if segment_addr <= section.vaddr < segment_addr + segment.memsize:
                    in_segment = True
                    break
            if not in_segment:
                continue

            # calculate alignments
            if section.vaddr % 0x20 == 0:
                alignment = 0x20
            elif section.vaddr % 0x10 == 0:
                alignment = 0x10
            elif section.vaddr % 0x8 == 0:
                alignment = 0x8
            elif section.vaddr % 0x4 == 0:
                alignment = 0x4
            else:
                alignment = 2

            self._section_alignments[section.name] = alignment

        l.debug('Generating CFG...')
        cfg = self.project.analyses.CFG(normalize=True, resolve_indirect_jumps=True, collect_data_references=True,
                                        extra_memory_regions=[(0x4347c000, 0x4347c000 + 0x1000)],
                                        data_type_guessing_handlers=[
                                            self._sequence_handler,
                                            self._cgc_extended_application_handler,
                                            self._unknown_data_size_handler,
                                        ],
                                        )

        self.cfg = cfg

        old_capstone_syntax = self.project.arch.capstone_x86_syntax
        if old_capstone_syntax is None:
            old_capstone_syntax = 'intel'

        if self.syntax == 'at&t':
            # switch capstone to AT&T style
            self.project.arch.capstone_x86_syntax = "at&t"
            # clear the block cache in lifter!
            self.project.factory.default_engine.clear_cache()

        # initialize symbol manager
        self.symbol_manager = SymbolManager(self, cfg)

        # collect address of all instructions
        l.debug('Collecting instruction addresses...')
        for cfg_node in self.cfg.nodes():
            self.all_insn_addrs |= set(cfg_node.instruction_addrs)

        # Functions

        l.debug('Creating functions...')
        for f in cfg.kb.functions.values():
            # Skip all SimProcedures
            if self.project.is_hooked(f.addr):
                continue
            elif self.project.simos.is_syscall_addr(f.addr):
                continue

            # Check which section the start address belongs to
            section = next(iter(sec.name for sec in self.project.loader.main_object.sections
                                if f.addr >= sec.vaddr and f.addr < sec.vaddr + sec.memsize
                                ),
                           ".text"
                           )

            if section in ('.got', '.plt', 'init', 'fini'):
                continue

            procedure = Procedure(self, f, section=section)
            self.procedures.append(procedure)

        self.procedures = sorted(self.procedures, key=lambda x: x.addr)

        # Data

        has_sections = len(self.project.loader.main_object.sections) > 0

        l.debug('Creating data entries...')
        for addr, memory_data in cfg._memory_data.items():

            if memory_data.sort in ('code reference', ):
                continue

            if memory_data.sort == 'string':
                # it might be the CGC package list
                new_sort, new_size = self._cgc_package_list_identifier(memory_data.address, memory_data.size)
                if new_sort is not None:
                    # oh we got it!
                    memory_data = memory_data.copy()
                    memory_data.sort = new_sort

            if has_sections:
                # Check which section the start address belongs to
                section = next(iter(sec for sec in self.project.loader.main_object.sections
                                    if sec.vaddr <= addr < sec.vaddr + sec.memsize
                                    ),
                               None
                               )

                if section is not None and section.name not in ('.note.gnu.build-id', ):  # ignore certain section names
                    data = Data(self, memory_data, section=section)
                    self.data.append(data)
                elif memory_data.sort == 'segment-boundary':
                    # it just points to the end of the segment or a section
                    section = next(iter(sec for sec in self.project.loader.main_object.sections
                                        if addr == sec.vaddr + sec.memsize),
                                   None
                                   )
                    if section is not None:
                        data = Data(self, memory_data, section=section)
                        self.data.append(data)

                else:
                    # data = Data(self, memory_data, section_name='.data')
                    # the data is not really within any existing section. weird. ignored it.
                    pass
            else:
                # the binary does not have any section
                # we use segment information instead
                # TODO: this logic needs reviewing
                segment = next(iter(seg for seg in self.project.loader.main_object.segments
                                    if seg.vaddr <= addr <= seg.vaddr + seg.memsize
                                    ),
                               None
                               )

                if segment is not None:
                    data = Data(self, memory_data, section_name='.data')
                    self.data.append(data)

        # remove all data that belong to GCC-specific sections
        section_names_to_ignore = {'.init', '.fini', '.fini_array', '.jcr', '.dynamic', '.got', '.got.plt',
                                   '.eh_frame_hdr', '.eh_frame', '.rel.dyn', '.rel.plt', '.rela.dyn', '.rela.plt',
                                   '.dynstr', '.dynsym', '.interp', '.note.ABI-tag', '.note.gnu.build-id', '.gnu.hash',
                                   '.gnu.version', '.gnu.version_r'
                                   }

        # make sure there are always memory data entries pointing at the end of sections
        all_data_addrs = set(d.addr for d in self.data)
        all_procedure_addrs = set(f.addr for f in self.procedures)
        all_addrs = all_data_addrs | all_procedure_addrs

        if has_sections:
            for section in self.project.loader.main_object.sections:

                if section.name in section_names_to_ignore:
                    # skip all sections that are CGC specific
                    continue

                # make sure this section is inside a segment
                for segment in self.project.loader.main_object.segments:
                    segment_start = segment.vaddr
                    segment_end = segment_start + segment.memsize
                    if segment_start <= section.vaddr < segment_end:
                        break
                else:
                    # this section is not mapped into memory
                    continue

                section_boundary_addr = section.vaddr + section.memsize
                if section_boundary_addr not in all_addrs:
                    data = Data(self, addr=section_boundary_addr, size=0, sort='segment-boundary',
                                section_name=section.name
                                )
                    self.data.append(data)
                    # add the address to all_data_addrs so we don't end up adding another boundary in
                    all_data_addrs.add(section_boundary_addr)

        self.data = sorted(self.data, key=lambda x: x.addr)

        data_indices_to_remove = set()

        # Go through data entry list and refine them
        for i, data in enumerate(self.data):

            if i in data_indices_to_remove:
                continue

            # process the overlapping ones
            if i < len(self.data) - 1:
                if data.addr + data.size > self.data[i + 1].addr:
                    # they are overlapping :-(

                    # TODO: make sure new_size makes sense
                    new_size = self.data[i + 1].addr - data.addr

                    # there are cases that legit data is misclassified as pointers
                    # we are able to detect some of them here
                    if data.sort == 'pointer-array':
                        pointer_size = self.project.arch.bytes
                        if new_size % pointer_size != 0:
                            # the self.data[i+1] cannot be pointed to by a pointer
                            # remove that guy later
                            data_indices_to_remove.add(i + 1)
                            # mark the source as a non-pointer
                            # apparently the original Reassembleable Disassembler paper cannot get this case
                            source_addr = self.data[i + 1].memory_data.pointer_addr
                            if source_addr is not None:
                                # find the original data
                                original_data = next((d for d in self.data if d.addr <= source_addr < d.addr + d.size),
                                                     None
                                                     )
                                if original_data is not None:
                                    original_data.desymbolize()

                            continue

                    data.shrink(new_size)

            # process those ones whose type is unknown
            if data.sort == 'unknown' and data.size == 0:
                # increase its size until reaching the next item

                if i + 1 == len(self.data):
                    if data.section is None:
                        continue
                    data.size = data.section.vaddr + data.section.memsize - data.addr
                else:
                    data.size = self.data[i + 1].addr - data.addr

        for i in sorted(data_indices_to_remove, reverse=True):
            self.data = self.data[ : i] + self.data[i + 1 : ]

        # CGC-specific data filtering
        self.data = [ d for d in self.data if d.section_name not in section_names_to_ignore ]

        # restore capstone X86 syntax at the end
        if self.project.arch.capstone_x86_syntax != old_capstone_syntax:
            self.project.arch.capstone_x86_syntax = old_capstone_syntax
            self.project.factory.default_engine.clear_cache()

        l.debug('Initialized.')