Class: Omnizip::Filters::BCJ
- Inherits:
-
Omnizip::Filter
- Object
- Omnizip::Filter
- Omnizip::Filters::BCJ
- Defined in:
- lib/omnizip/filters/bcj.rb
Overview
Unified BCJ (Branch/Call/Jump) filter for multiple architectures
This filter preprocesses executable code by converting relative addresses in branch/call instructions to absolute addresses. The transformation is reversible and improves compression ratio.
Supports x86, ARM, ARM Thumb, ARM64, PowerPC, IA64, SPARC architectures. Automatically returns correct filter ID for 7z or XZ format.
Constant Summary collapse
- CONFIG =
Architecture-specific configurations
{ x86: { opcodes: [0xE8, 0xE9], # CALL, JMP address_size: 4, instruction_size: 5, xz_id: 0x04, seven_zip_id: 0x03030103, }, arm: { opcodes: [0x0A, 0x0B], # ARM BL/B conditional address_size: 4, instruction_size: 4, xz_id: 0x07, seven_zip_id: 0x03030501, }, armthumb: { opcodes: [0xE8, 0xF0, 0xF1], # ARM Thumb BL/B conditional address_size: 4, instruction_size: 4, xz_id: 0x08, seven_zip_id: 0x03030701, }, arm64: { opcodes: [0x00], # ARM64 BL address_size: 4, instruction_size: 4, xz_id: nil, # Not yet in XZ seven_zip_id: 0x03030601, }, powerpc: { opcodes: [0x48, 0x18], # PowerPC branch instructions address_size: 4, instruction_size: 4, xz_id: 0x05, seven_zip_id: 0x03030205, }, ia64: { opcodes: [0x04, 0x05, 0x06, 0x07, 0x08], # IA64 branches address_size: 4, instruction_size: 4, xz_id: 0x06, seven_zip_id: 0x03030401, }, sparc: { opcodes: [0x04, 0x06, 0x07], # SPARC call/branch address_size: 4, instruction_size: 4, xz_id: 0x09, seven_zip_id: 0x03030805, }, }.freeze
Instance Attribute Summary collapse
-
#architecture ⇒ Symbol
readonly
Architecture identifier.
Attributes inherited from Omnizip::Filter
Class Method Summary collapse
-
.metadata ⇒ Hash
Get metadata about this filter.
Instance Method Summary collapse
-
#decode(data, position = 0) ⇒ String
Decode (postprocess) data after decompression.
-
#encode(data, position = 0) ⇒ String
Encode (preprocess) data for compression.
-
#id_for_format(format) ⇒ Integer
Get filter ID for specific format.
-
#initialize(architecture:) ⇒ BCJ
constructor
Initialize BCJ filter for specific architecture.
Constructor Details
#initialize(architecture:) ⇒ BCJ
Initialize BCJ filter for specific architecture
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/omnizip/filters/bcj.rb', line 100 def initialize(architecture:) unless CONFIG.key?(architecture) raise ArgumentError, "Unsupported BCJ architecture: #{architecture}. " \ "Supported: #{CONFIG.keys.join(', ')}" end @architecture = architecture @config = CONFIG[architecture] super(architecture: architecture, name: "BCJ-#{architecture.to_s.upcase}") end |
Instance Attribute Details
#architecture ⇒ Symbol (readonly)
Returns Architecture identifier.
94 95 96 |
# File 'lib/omnizip/filters/bcj.rb', line 94 def architecture @architecture end |
Class Method Details
.metadata ⇒ Hash
Get metadata about this filter
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/omnizip/filters/bcj.rb', line 215 def { name: "BCJ", description: "Branch/Call/Jump converter for executable files", supported_architectures: CONFIG.keys, architectures: { x86: "x86/x86-64", arm: "ARM 32-bit", arm64: "ARM 64-bit", powerpc: "PowerPC", ia64: "IA-64 (Itanium)", sparc: "SPARC", }, } end |
Instance Method Details
#decode(data, position = 0) ⇒ String
Decode (postprocess) data after decompression
Reverses encoding by converting absolute addresses back to relative addresses.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/omnizip/filters/bcj.rb', line 181 def decode(data, position = 0) return data.dup if data.bytesize < @config[:instruction_size] result = data.b i = 0 limit = data.bytesize - @config[:instruction_size] while i <= limit opcode = result.getbyte(i) if @config[:opcodes].include?(opcode) # Extract absolute address absolute = extract_address(result, i + 1) # Convert to relative address = absolute - (position + i + @config[:instruction_size]) if valid_relative_address?(address) write_address(result, i + 1, address) end i += @config[:instruction_size] else i += 1 end end result end |
#encode(data, position = 0) ⇒ String
Encode (preprocess) data for compression
Scans for branch/call opcodes and converts relative addresses to absolute addresses.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/omnizip/filters/bcj.rb', line 143 def encode(data, position = 0) return data.dup if data.bytesize < @config[:instruction_size] result = data.b i = 0 limit = data.bytesize - @config[:instruction_size] while i <= limit opcode = result.getbyte(i) if @config[:opcodes].include?(opcode) # Extract address (little-endian) address = extract_address(result, i + 1) # Check if valid relative address if valid_relative_address?(address) # Convert to absolute absolute = address + position + i + @config[:instruction_size] write_address(result, i + 1, absolute) end i += @config[:instruction_size] else i += 1 end end result end |
#id_for_format(format) ⇒ Integer
Get filter ID for specific format
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/omnizip/filters/bcj.rb', line 117 def id_for_format(format) case format when :seven_zip @config[:seven_zip_id] when :xz id = @config[:xz_id] if id.nil? raise NotImplementedError, "#{@architecture} BCJ not yet supported in XZ format" end id else raise ArgumentError, "Unknown format: #{format}. Supported: :seven_zip, :xz" end end |