text: #!/usr/bin/python
  
  from enum import IntEnum
  import sys
  
  """ Parse a `readelf -wF` output, trying to locate CFA=f(rbp) to CFA=g(rsp) changes,
  and to detect the offset applied to rsp in such cases. """
  
  
  class Eof(Exception):
      pass
  
  
  program_name = sys.argv[1]
  
  
  def log_entry(entry):
      print("[{}] {}".format(program_name, entry))
  
  
  def parse_line(line):
      spl = line.strip().split(" ")
      addr = int(spl[0], 16)
      cfa = spl[1]
      return addr, cfa
  
  
  def match_fde_header(line):
      spl = line.strip().split()
      if len(spl) == 6 and spl[3] == "FDE":
          return True
      return False
  
  
  class CfaType(IntEnum):
      OTHER = 0
      RSP_BASED = 1
      RBP_BASED = 2
  
  
  def get_cfa_type(cfa):
      if cfa.startswith("rsp"):
          return CfaType.RSP_BASED
      if cfa.startswith("rbp"):
          return CfaType.RBP_BASED
      return CfaType.OTHER
  
  
  def parse_fde(lines):
      # Read until FDE head
      for line in lines:
          if match_fde_header(line):
              break
  
      try:
          post_header = next(lines)  # Waste a line — FDE columns head
          if not post_header.strip():  # Empty FDE — return now
              return True
      except StopIteration:
          return False
  
      # Read each row until an empty line is found
  
      prev_rbp = False  # Was the last line rbp indexed?
      closed_rbp_block = False  # Was there already a rbp-indexed block which is over?
      for line in lines:
          line = line.strip()
          if not line:  # Empty line — FDE end
              return True
  
          addr, cfa = parse_line(line)
          cfa_type = get_cfa_type(cfa)
  
          if cfa_type == CfaType.RSP_BASED and prev_rbp:
              closed_rbp_block = True
              if cfa != "rsp+8":
                  log_entry(
                      "(E) {}: CFA={} after %rbp-based index".format(hex(addr), cfa)
                  )
  
          if cfa_type == CfaType.RBP_BASED:
              prev_rbp = True
              if closed_rbp_block:
                  log_entry("(W) {}: two %rbp blocks in function".format(addr))
          else:
              prev_rbp = False
  
      return False
  
  
  if __name__ == "__main__":
      handle = sys.stdin
      while parse_fde(handle):
          pass
  