| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "courgette/encoded_program.h" | 5 #include "courgette/encoded_program.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/environment.h" | 12 #include "base/environment.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "courgette/courgette.h" | 17 #include "courgette/courgette.h" |
| 18 #include "courgette/streams.h" | 18 #include "courgette/streams.h" |
| 19 #include "courgette/types_elf.h" |
| 19 | 20 |
| 20 namespace courgette { | 21 namespace courgette { |
| 21 | 22 |
| 22 // Stream indexes. | 23 // Stream indexes. |
| 23 const int kStreamMisc = 0; | 24 const int kStreamMisc = 0; |
| 24 const int kStreamOps = 1; | 25 const int kStreamOps = 1; |
| 25 const int kStreamBytes = 2; | 26 const int kStreamBytes = 2; |
| 26 const int kStreamAbs32Indexes = 3; | 27 const int kStreamAbs32Indexes = 3; |
| 27 const int kStreamRel32Indexes = 4; | 28 const int kStreamRel32Indexes = 4; |
| 28 const int kStreamAbs32Addresses = 5; | 29 const int kStreamAbs32Addresses = 5; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 } | 235 } |
| 235 | 236 |
| 236 CheckBool EncodedProgram::AddAbs32(int label_index) { | 237 CheckBool EncodedProgram::AddAbs32(int label_index) { |
| 237 return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index); | 238 return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index); |
| 238 } | 239 } |
| 239 | 240 |
| 240 CheckBool EncodedProgram::AddRel32(int label_index) { | 241 CheckBool EncodedProgram::AddRel32(int label_index) { |
| 241 return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); | 242 return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); |
| 242 } | 243 } |
| 243 | 244 |
| 244 CheckBool EncodedProgram::AddMakeRelocs() { | 245 CheckBool EncodedProgram::AddPeMakeRelocs() { |
| 245 return ops_.push_back(MAKE_BASE_RELOCATION_TABLE); | 246 return ops_.push_back(MAKE_PE_RELOCATION_TABLE); |
| 247 } |
| 248 |
| 249 CheckBool EncodedProgram::AddElfMakeRelocs() { |
| 250 return ops_.push_back(MAKE_ELF_RELOCATION_TABLE); |
| 246 } | 251 } |
| 247 | 252 |
| 248 void EncodedProgram::DebuggingSummary() { | 253 void EncodedProgram::DebuggingSummary() { |
| 249 VLOG(1) << "EncodedProgram Summary" | 254 VLOG(1) << "EncodedProgram Summary" |
| 250 << "\n image base " << image_base_ | 255 << "\n image base " << image_base_ |
| 251 << "\n abs32 rvas " << abs32_rva_.size() | 256 << "\n abs32 rvas " << abs32_rva_.size() |
| 252 << "\n rel32 rvas " << rel32_rva_.size() | 257 << "\n rel32 rvas " << rel32_rva_.size() |
| 253 << "\n ops " << ops_.size() | 258 << "\n ops " << ops_.size() |
| 254 << "\n origins " << origins_.size() | 259 << "\n origins " << origins_.size() |
| 255 << "\n copy_counts " << copy_counts_.size() | 260 << "\n copy_counts " << copy_counts_.size() |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 // For the most part, the assembly process walks the various tables. | 397 // For the most part, the assembly process walks the various tables. |
| 393 // ix_mumble is the index into the mumble table. | 398 // ix_mumble is the index into the mumble table. |
| 394 size_t ix_origins = 0; | 399 size_t ix_origins = 0; |
| 395 size_t ix_copy_counts = 0; | 400 size_t ix_copy_counts = 0; |
| 396 size_t ix_copy_bytes = 0; | 401 size_t ix_copy_bytes = 0; |
| 397 size_t ix_abs32_ix = 0; | 402 size_t ix_abs32_ix = 0; |
| 398 size_t ix_rel32_ix = 0; | 403 size_t ix_rel32_ix = 0; |
| 399 | 404 |
| 400 RVA current_rva = 0; | 405 RVA current_rva = 0; |
| 401 | 406 |
| 402 bool pending_base_relocation_table = false; | 407 bool pending_pe_relocation_table = false; |
| 403 SinkStream bytes_following_base_relocation_table; | 408 bool pending_elf_relocation_table = false; |
| 409 SinkStream bytes_following_relocation_table; |
| 404 | 410 |
| 405 SinkStream* output = final_buffer; | 411 SinkStream* output = final_buffer; |
| 406 | 412 |
| 407 for (size_t ix_ops = 0; ix_ops < ops_.size(); ++ix_ops) { | 413 for (size_t ix_ops = 0; ix_ops < ops_.size(); ++ix_ops) { |
| 408 OP op = ops_[ix_ops]; | 414 OP op = ops_[ix_ops]; |
| 409 | 415 |
| 410 switch (op) { | 416 switch (op) { |
| 411 default: | 417 default: |
| 412 return false; | 418 return false; |
| 413 | 419 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 RVA rva; | 477 RVA rva; |
| 472 if (!VectorAt(abs32_rva_, index, &rva)) | 478 if (!VectorAt(abs32_rva_, index, &rva)) |
| 473 return false; | 479 return false; |
| 474 uint32 abs32 = static_cast<uint32>(rva + image_base_); | 480 uint32 abs32 = static_cast<uint32>(rva + image_base_); |
| 475 if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4)) | 481 if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4)) |
| 476 return false; | 482 return false; |
| 477 current_rva += 4; | 483 current_rva += 4; |
| 478 break; | 484 break; |
| 479 } | 485 } |
| 480 | 486 |
| 481 case MAKE_BASE_RELOCATION_TABLE: { | 487 case MAKE_PE_RELOCATION_TABLE: { |
| 482 // We can see the base relocation anywhere, but we only have the | 488 // We can see the base relocation anywhere, but we only have the |
| 483 // information to generate it at the very end. So we divert the bytes | 489 // information to generate it at the very end. So we divert the bytes |
| 484 // we are generating to a temporary stream. | 490 // we are generating to a temporary stream. |
| 485 if (pending_base_relocation_table) // Can't have two base relocation | 491 if (pending_pe_relocation_table) // Can't have two base relocation |
| 486 // tables. | 492 // tables. |
| 487 return false; | 493 return false; |
| 488 | 494 |
| 489 pending_base_relocation_table = true; | 495 pending_pe_relocation_table = true; |
| 490 output = &bytes_following_base_relocation_table; | 496 output = &bytes_following_relocation_table; |
| 491 break; | 497 break; |
| 492 // There is a potential problem *if* the instruction stream contains | 498 // There is a potential problem *if* the instruction stream contains |
| 493 // some REL32 relocations following the base relocation and in the same | 499 // some REL32 relocations following the base relocation and in the same |
| 494 // section. We don't know the size of the table, so 'current_rva' will | 500 // section. We don't know the size of the table, so 'current_rva' will |
| 495 // be wrong, causing REL32 offsets to be miscalculated. This never | 501 // be wrong, causing REL32 offsets to be miscalculated. This never |
| 496 // happens; the base relocation table is usually in a section of its | 502 // happens; the base relocation table is usually in a section of its |
| 497 // own, a data-only section, and following everything else in the | 503 // own, a data-only section, and following everything else in the |
| 498 // executable except some padding zero bytes. We could fix this by | 504 // executable except some padding zero bytes. We could fix this by |
| 499 // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE. | 505 // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE. |
| 500 } | 506 } |
| 507 |
| 508 case MAKE_ELF_RELOCATION_TABLE: { |
| 509 // We can see the base relocation anywhere, but we only have the |
| 510 // information to generate it at the very end. So we divert the bytes |
| 511 // we are generating to a temporary stream. |
| 512 if (pending_elf_relocation_table) // Can't have two relocation |
| 513 // tables. |
| 514 return false; |
| 515 |
| 516 pending_elf_relocation_table = true; |
| 517 output = &bytes_following_relocation_table; |
| 518 break; |
| 519 } |
| 501 } | 520 } |
| 502 } | 521 } |
| 503 | 522 |
| 504 if (pending_base_relocation_table) { | 523 if (pending_pe_relocation_table) { |
| 505 if (!GenerateBaseRelocations(final_buffer) || | 524 if (!GeneratePeRelocations(final_buffer) || |
| 506 !final_buffer->Append(&bytes_following_base_relocation_table)) | 525 !final_buffer->Append(&bytes_following_relocation_table)) |
| 507 return false; | 526 return false; |
| 508 } | 527 } |
| 509 | 528 |
| 529 if (pending_elf_relocation_table) { |
| 530 if (!GenerateElfRelocations(final_buffer) || |
| 531 !final_buffer->Append(&bytes_following_relocation_table)) |
| 532 return false; |
| 533 } |
| 534 |
| 510 // Final verification check: did we consume all lists? | 535 // Final verification check: did we consume all lists? |
| 511 if (ix_copy_counts != copy_counts_.size()) | 536 if (ix_copy_counts != copy_counts_.size()) |
| 512 return false; | 537 return false; |
| 513 if (ix_copy_bytes != copy_bytes_.size()) | 538 if (ix_copy_bytes != copy_bytes_.size()) |
| 514 return false; | 539 return false; |
| 515 if (ix_abs32_ix != abs32_ix_.size()) | 540 if (ix_abs32_ix != abs32_ix_.size()) |
| 516 return false; | 541 return false; |
| 517 if (ix_rel32_ix != rel32_ix_.size()) | 542 if (ix_rel32_ix != rel32_ix_.size()) |
| 518 return false; | 543 return false; |
| 519 | 544 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 550 Add(0); | 575 Add(0); |
| 551 } | 576 } |
| 552 ok = buffer->Write(&pod, pod.block_size); | 577 ok = buffer->Write(&pod, pod.block_size); |
| 553 pod.block_size = 8; | 578 pod.block_size = 8; |
| 554 } | 579 } |
| 555 return ok; | 580 return ok; |
| 556 } | 581 } |
| 557 RelocBlockPOD pod; | 582 RelocBlockPOD pod; |
| 558 }; | 583 }; |
| 559 | 584 |
| 560 CheckBool EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) { | 585 CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) { |
| 561 std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); | 586 std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); |
| 562 | 587 |
| 563 RelocBlock block; | 588 RelocBlock block; |
| 564 | 589 |
| 565 bool ok = true; | 590 bool ok = true; |
| 566 for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { | 591 for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { |
| 567 uint32 rva = abs32_relocs_[i]; | 592 uint32 rva = abs32_relocs_[i]; |
| 568 uint32 page_rva = rva & ~0xFFF; | 593 uint32 page_rva = rva & ~0xFFF; |
| 569 if (page_rva != block.pod.page_rva) { | 594 if (page_rva != block.pod.page_rva) { |
| 570 ok &= block.Flush(buffer); | 595 ok &= block.Flush(buffer); |
| 571 block.pod.page_rva = page_rva; | 596 block.pod.page_rva = page_rva; |
| 572 } | 597 } |
| 573 if (ok) | 598 if (ok) |
| 574 block.Add(0x3000 | (rva & 0xFFF)); | 599 block.Add(0x3000 | (rva & 0xFFF)); |
| 575 } | 600 } |
| 576 ok &= block.Flush(buffer); | 601 ok &= block.Flush(buffer); |
| 577 return ok; | 602 return ok; |
| 578 } | 603 } |
| 579 | 604 |
| 605 CheckBool EncodedProgram::GenerateElfRelocations(SinkStream* buffer) { |
| 606 std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); |
| 607 |
| 608 Elf32_Rel relocation_block; |
| 609 |
| 610 // We only handle this specific type of relocation, so far. |
| 611 relocation_block.r_info = R_386_RELATIVE; |
| 612 |
| 613 bool ok = true; |
| 614 for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { |
| 615 relocation_block.r_offset = abs32_relocs_[i]; |
| 616 ok = buffer->Write(&relocation_block, sizeof(Elf32_Rel)); |
| 617 } |
| 618 |
| 619 return ok; |
| 620 } |
| 580 //////////////////////////////////////////////////////////////////////////////// | 621 //////////////////////////////////////////////////////////////////////////////// |
| 581 | 622 |
| 582 Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { | 623 Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { |
| 583 if (!encoded->WriteTo(sink)) | 624 if (!encoded->WriteTo(sink)) |
| 584 return C_STREAM_ERROR; | 625 return C_STREAM_ERROR; |
| 585 return C_OK; | 626 return C_OK; |
| 586 } | 627 } |
| 587 | 628 |
| 588 Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) { | 629 Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) { |
| 589 EncodedProgram* encoded = new EncodedProgram(); | 630 EncodedProgram* encoded = new EncodedProgram(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 600 if (assembled) | 641 if (assembled) |
| 601 return C_OK; | 642 return C_OK; |
| 602 return C_ASSEMBLY_FAILED; | 643 return C_ASSEMBLY_FAILED; |
| 603 } | 644 } |
| 604 | 645 |
| 605 void DeleteEncodedProgram(EncodedProgram* encoded) { | 646 void DeleteEncodedProgram(EncodedProgram* encoded) { |
| 606 delete encoded; | 647 delete encoded; |
| 607 } | 648 } |
| 608 | 649 |
| 609 } // end namespace | 650 } // end namespace |
| OLD | NEW |