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 |