* Parse a patch message. */
| 359 | * Parse a patch message. |
| 360 | */ |
| 361 | static void parsePatch(Binary *B, const Message &msg) |
| 362 | { |
| 363 | const Trampoline *T = nullptr; |
| 364 | off_t offset = 0; |
| 365 | Metadata *meta = nullptr; |
| 366 | bool have_offset = false, dup = false; |
| 367 | for (unsigned i = 0; i < msg.num_params; i++) |
| 368 | { |
| 369 | switch (msg.params[i].name) |
| 370 | { |
| 371 | case PARAM_TRAMPOLINE: |
| 372 | dup = dup || (T != nullptr); |
| 373 | T = msg.params[i].value.trampoline; |
| 374 | break; |
| 375 | case PARAM_OFFSET: |
| 376 | dup = dup || have_offset; |
| 377 | offset = (off_t)msg.params[i].value.integer; |
| 378 | have_offset = true; |
| 379 | break; |
| 380 | case PARAM_METADATA: |
| 381 | dup = dup || (meta != nullptr); |
| 382 | meta = msg.params[i].value.metadata; |
| 383 | break; |
| 384 | default: |
| 385 | break; |
| 386 | } |
| 387 | } |
| 388 | if (T == nullptr) |
| 389 | error("failed to parse \"patch\" message (id=%u); missing " |
| 390 | "\"trampoline\" parameter", msg.id); |
| 391 | if (!have_offset) |
| 392 | error("failed to parse \"patch\" message (id=%u); missing " |
| 393 | "\"offset\" parameter", msg.id); |
| 394 | if (dup) |
| 395 | error("failed to parse \"patch\" message (id=%u); duplicate " |
| 396 | "parameters detected", msg.id); |
| 397 | |
| 398 | Instr *I = B->Is.find(offset); |
| 399 | if (I == nullptr) |
| 400 | error("failed to parse \"patch\" message (id=%u); no matching " |
| 401 | "instruction at offset (%zd)", msg.id, offset); |
| 402 | if (I->patch) |
| 403 | error("failed to parse \"patch\" message (id=%u); instruction " |
| 404 | "at address (0x%lx) is already queued for patching", msg.id, |
| 405 | I->addr); |
| 406 | I->patch = true; |
| 407 | I->metadata = meta; |
| 408 | I->T = T; |
| 409 | |
| 410 | queuePatch(B, I, T); |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | * Parse an emit message. |
no test coverage detected