module CocoapodsMangle::Defines

Generates mangling defines from a provided list of binaries

Public Class Methods

category_selectors(binaries, classes) click to toggle source

Get the category selectors defined in a list of binaries @note Selectors on classes which are being mangled will not be mangled @param [Array<String>] binaries

The binaries containing symbols to be mangled

@param [Array<String>] classes

The classes which are being mangled

@return [Array<String>] The category selectors defined in the binaries

# File lib/cocoapods_mangle/defines.rb, line 65
def self.category_selectors(binaries, classes)
  symbols = run_nm(binaries, '-U')
  selectors = symbols.select { |selector| selector[/ t [-|+]\[[^ ]*\([^ ]*\) [^ ]*\]/] }
  selectors = selectors.reject do |selector|
    class_name = selector[/[-|+]\[(.*?)\(/m, 1]
    classes.include? class_name
  end
  selectors = selectors.map { |selector| selector[/[^ ]*\]\z/][0...-1] }
  selectors = selectors.map { |selector| selector.split(':').first }
  selectors.uniq
end
classes(binaries) click to toggle source

Get the classes defined in a list of binaries @param [Array<String>] binaries

The binaries containing symbols to be mangled

@return [Array<String>] The classes defined in the binaries

# File lib/cocoapods_mangle/defines.rb, line 24
def self.classes(binaries)
  all_symbols = run_nm(binaries, '-gU')
  all_symbols = all_symbols.reject { |symbol| swift_symbol?(symbol) }

  class_symbols = all_symbols.select do |symbol|
    symbol[/OBJC_CLASS_\$_/]
  end
  class_symbols = class_symbols.map { |klass| klass.gsub(/^.*\$_/, '') }
  class_symbols.uniq
end
constants(binaries) click to toggle source

Get the constants defined in a list of binaries @param [Array<String>] binaries

The binaries containing symbols to be mangled

@return [Array<String>] The constants defined in the binaries

# File lib/cocoapods_mangle/defines.rb, line 39
def self.constants(binaries)
  all_symbols = run_nm(binaries, '-gU')
  all_symbols = all_symbols.reject { |symbol| swift_symbol?(symbol) }

  consts = all_symbols.select { |const| const[/ S /] }
  consts = consts.reject { |const| const[/_OBJC_/] }
  consts = consts.reject { |const| const[/__block_descriptor.*/] }
  consts = consts.map! { |const| const.gsub(/^.* _/, '') }
  consts = consts.uniq

  other_consts = all_symbols.select { |const| const[/ T /] }
  other_consts = other_consts.reject { |const| const[/__copy_helper_block.*/] }
  other_consts = other_consts.reject { |const| const[/__destroy_helper_block.*/] }
  other_consts = other_consts.map! { |const| const.gsub(/^.* _/, '') }
  other_consts = other_consts.uniq

  consts + other_consts
end
mangling_defines(prefix, binaries_to_mangle) click to toggle source

@param [String] prefix

The prefix to prefix to mangled symbols

@param [Array<String>] binaries_to_mangle

The binaries containing symbols to be mangled

@return [Array<String>] The mangling defines

# File lib/cocoapods_mangle/defines.rb, line 9
def self.mangling_defines(prefix, binaries_to_mangle)
  classes = classes(binaries_to_mangle)
  constants = constants(binaries_to_mangle)
  category_selectors = category_selectors(binaries_to_mangle, classes)

  defines = prefix_symbols(prefix, classes)
  defines += prefix_symbols(prefix, constants)
  defines += prefix_selectors(prefix, category_selectors)
  defines
end
prefix_selectors(prefix, selectors) click to toggle source

Prefix a given list of selectors @param [String] prefix

The prefix to use

@param [Array<String>] selectors

The selectors to prefix
# File lib/cocoapods_mangle/defines.rb, line 93
def self.prefix_selectors(prefix, selectors)
  selectors_to_prefix = selectors
  defines = []

  property_setters = selectors.select { |selector| selector[/\Aset[A-Z]/] }
  property_setters.each do |property_setter|
    property_getter = selectors.find do |selector|
      upper_getter = property_setter[3..-1]
      lower_getter = upper_getter[0, 1].downcase + upper_getter[1..-1]
      selector == upper_getter || selector == lower_getter
    end
    next if property_getter.nil?

    selectors_to_prefix.reject! { |selector| selector == property_setter }
    selectors_to_prefix.reject! { |selector| selector == property_getter }

    defines << "#{property_setter}=set#{prefix}#{property_getter}"
    defines << "#{property_getter}=#{prefix}#{property_getter}"
  end

  defines += prefix_symbols(prefix, selectors_to_prefix)
  defines
end
prefix_symbols(prefix, symbols) click to toggle source

Prefix a given list of symbols @param [String] prefix

The prefix to prepend

@param [Array<String>] symbols

The symbols to prefix
# File lib/cocoapods_mangle/defines.rb, line 82
def self.prefix_symbols(prefix, symbols)
  symbols.map do |symbol|
    "#{symbol}=#{prefix}#{symbol}"
  end
end
run_nm(binaries, flags) click to toggle source
# File lib/cocoapods_mangle/defines.rb, line 142
def self.run_nm(binaries, flags)
  `nm #{flags} #{binaries.join(' ')}`.split("\n")
end
swift_symbol?(symbol) click to toggle source

Is symbol a Swift symbol? This is used to avoid mangling Swift. @param [String] symbol

The symbol to check

@return [Boolean] true if it is a Swift symbol, false otherwise

# File lib/cocoapods_mangle/defines.rb, line 121
def self.swift_symbol?(symbol)
  # Swift binaries have many symbols starting with $s_ that should be excluded
  # e.g. '0000000000000258 S _$s9ManglePod9SomeClassCMF'
  symbol[/ _\$s/] ||
    # Internal Swift symbols starting with __swift or ___swift such as should not be mangled
    # e.g. '00000000000050ac S ___swift_reflection_version'
    symbol[/ __(_)?swift/] ||
    # Swift symbols starting with _symbolic should be ignored
    # e.g. '0000000000000248 S _symbolic _____ 9ManglePod9SomeClassC'
    symbol[/ _symbolic/] ||
    # Swift symbol references to Objective-C symbols should not be mangled
    # e.g. '00000000000108ca S _associated conformance So26SCNetworkReachabilityFlagsVs10SetAlgebraSCSQ'
    symbol[/associated conformance/] ||
    # _globalinit symbols should be skipped
    # e.g. 0000000000000000 T _globalinit_33_A313450CFC1FC3D0CBEF4411412DB9E8_func0
    symbol[/ _globalinit/] ||
    # Swift classes inheriting from Objective-C classes should not be mangled
    # e.g. '0000000000000290 S _OBJC_CLASS_$__TtC9ManglePod19SomeFoundationClass'
    symbol[/_OBJC_CLASS_\$__/]
end