docs: 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.')