summaryrefslogtreecommitdiffstats
path: root/courgette/encoded_program.cc
diff options
context:
space:
mode:
authorpaulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 00:11:24 +0000
committerpaulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 00:11:24 +0000
commit2b637b698c76e43c9cf729e868cf7618d5327cc8 (patch)
tree91aeaa633d613ec7fa34a1073eb48bf26af7a8c7 /courgette/encoded_program.cc
parent1c9bf75724817afb7cfa9b3bfdf917b01b8a667f (diff)
downloadchromium_src-2b637b698c76e43c9cf729e868cf7618d5327cc8.zip
chromium_src-2b637b698c76e43c9cf729e868cf7618d5327cc8.tar.gz
chromium_src-2b637b698c76e43c9cf729e868cf7618d5327cc8.tar.bz2
Support for ARM 32-bit ELF binaries in Courgette
Notes for reviewers: dgarrett: courgette correctness, ARM benchan: style, correctness BUG=258640,258645,258653 Review URL: https://chromiumcodereview.appspot.com/20099004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/encoded_program.cc')
-rw-r--r--courgette/encoded_program.cc122
1 files changed, 121 insertions, 1 deletions
diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc
index b7c9b55..c619c6a 100644
--- a/courgette/encoded_program.cc
+++ b/courgette/encoded_program.cc
@@ -243,6 +243,11 @@ CheckBool EncodedProgram::AddRel32(int label_index) {
return ops_.push_back(REL32) && rel32_ix_.push_back(label_index);
}
+CheckBool EncodedProgram::AddRel32ARM(uint16 op, int label_index) {
+ return ops_.push_back(static_cast<OP>(op)) &&
+ rel32_ix_.push_back(label_index);
+}
+
CheckBool EncodedProgram::AddPeMakeRelocs() {
return ops_.push_back(MAKE_PE_RELOCATION_TABLE);
}
@@ -398,6 +403,119 @@ bool VectorAt(const V& v, size_t index, T* output) {
return true;
}
+CheckBool EncodedProgram::EvaluateRel32ARM(OP op,
+ size_t& ix_rel32_ix,
+ RVA& current_rva,
+ SinkStream* output) {
+ switch (op & 0x0000F000) {
+ case REL32ARM8: {
+ uint32 index;
+ if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
+ return false;
+ ++ix_rel32_ix;
+ RVA rva;
+ if (!VectorAt(rel32_rva_, index, &rva))
+ return false;
+ uint32 decompressed_op;
+ if (!DisassemblerElf32ARM::Decompress(ARM_OFF8,
+ static_cast<uint16>(op),
+ static_cast<uint32>(rva -
+ current_rva),
+ &decompressed_op)) {
+ return false;
+ }
+ uint16 op16 = decompressed_op;
+ if (!output->Write(&op16, 2))
+ return false;
+ current_rva += 2;
+ break;
+ }
+ case REL32ARM11: {
+ uint32 index;
+ if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
+ return false;
+ ++ix_rel32_ix;
+ RVA rva;
+ if (!VectorAt(rel32_rva_, index, &rva))
+ return false;
+ uint32 decompressed_op;
+ if (!DisassemblerElf32ARM::Decompress(ARM_OFF11, (uint16) op,
+ (uint32) (rva - current_rva),
+ &decompressed_op)) {
+ return false;
+ }
+ uint16 op16 = decompressed_op;
+ if (!output->Write(&op16, 2))
+ return false;
+ current_rva += 2;
+ break;
+ }
+ case REL32ARM24: {
+ uint32 index;
+ if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
+ return false;
+ ++ix_rel32_ix;
+ RVA rva;
+ if (!VectorAt(rel32_rva_, index, &rva))
+ return false;
+ uint32 decompressed_op;
+ if (!DisassemblerElf32ARM::Decompress(ARM_OFF24, (uint16) op,
+ (uint32) (rva - current_rva),
+ &decompressed_op)) {
+ return false;
+ }
+ if (!output->Write(&decompressed_op, 4))
+ return false;
+ current_rva += 4;
+ break;
+ }
+ case REL32ARM25: {
+ uint32 index;
+ if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
+ return false;
+ ++ix_rel32_ix;
+ RVA rva;
+ if (!VectorAt(rel32_rva_, index, &rva))
+ return false;
+ uint32 decompressed_op;
+ if (!DisassemblerElf32ARM::Decompress(ARM_OFF25, (uint16) op,
+ (uint32) (rva - current_rva),
+ &decompressed_op)) {
+ return false;
+ }
+ uint32 words = (decompressed_op << 16) | (decompressed_op >> 16);
+ if (!output->Write(&words, 4))
+ return false;
+ current_rva += 4;
+ break;
+ }
+ case REL32ARM21: {
+ uint32 index;
+ if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
+ return false;
+ ++ix_rel32_ix;
+ RVA rva;
+ if (!VectorAt(rel32_rva_, index, &rva))
+ return false;
+ uint32 decompressed_op;
+ if (!DisassemblerElf32ARM::Decompress(ARM_OFF21, (uint16) op,
+ (uint32) (rva - current_rva),
+ &decompressed_op)) {
+ return false;
+ }
+ uint32 words = (decompressed_op << 16) | (decompressed_op >> 16);
+ if (!output->Write(&words, 4))
+ return false;
+ current_rva += 4;
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
// For the most part, the assembly process walks the various tables.
// ix_mumble is the index into the mumble table.
@@ -420,7 +538,9 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
switch (op) {
default:
- return false;
+ if (!EvaluateRel32ARM(op, ix_rel32_ix, current_rva, output))
+ return false;
+ break;
case ORIGIN: {
RVA section_rva;