Merge "Add stub for x86 & x86_64."
diff --git a/cpu_ref/linkloader/include/ELFSectionProgBits.h b/cpu_ref/linkloader/include/ELFSectionProgBits.h
index 3a973f7..a642b16 100644
--- a/cpu_ref/linkloader/include/ELFSectionProgBits.h
+++ b/cpu_ref/linkloader/include/ELFSectionProgBits.h
@@ -44,19 +44,27 @@
ELFSectionProgBits(int machine) {
switch(machine) {
case EM_ARM:
- stubs = new StubLayoutARM();
+ stubs = new StubLayoutARM();
break;
case EM_AARCH64:
- stubs = new StubLayoutAARCH64();
+ stubs = new StubLayoutAARCH64();
break;
case EM_MIPS:
- stubs = new StubLayoutMIPS();
+ stubs = new StubLayoutMIPS();
+ break;
+
+ case EM_386:
+ stubs = new StubLayoutX86();
+ break;
+
+ case EM_X86_64:
+ stubs = new StubLayoutX86_64();
break;
default:
- stubs = NULL;
+ stubs = NULL;
}
}
diff --git a/cpu_ref/linkloader/include/StubLayout.h b/cpu_ref/linkloader/include/StubLayout.h
index 436c18e..0c2e950 100644
--- a/cpu_ref/linkloader/include/StubLayout.h
+++ b/cpu_ref/linkloader/include/StubLayout.h
@@ -69,5 +69,22 @@
virtual void setStubAddress(void *stub, void *addr);
};
+class StubLayoutX86 : public StubLayout {
+public:
+ StubLayoutX86() { }
+ size_t getUnitStubSize() const;
+
+private:
+ virtual void setStubAddress(void *stub, void *addr);
+};
+
+class StubLayoutX86_64 : public StubLayout {
+public:
+ StubLayoutX86_64() { }
+ size_t getUnitStubSize() const;
+
+private:
+ virtual void setStubAddress(void *stub, void *addr);
+};
#endif // STUB_LAYOUT_H
diff --git a/cpu_ref/linkloader/lib/StubLayout.cpp b/cpu_ref/linkloader/lib/StubLayout.cpp
index 609ec76..08842e8 100644
--- a/cpu_ref/linkloader/lib/StubLayout.cpp
+++ b/cpu_ref/linkloader/lib/StubLayout.cpp
@@ -128,3 +128,36 @@
stub[2] = 0x03200008ul; // jr (jump register)
stub[3] = 0x00000000ul; // nop
}
+
+size_t StubLayoutX86::getUnitStubSize() const {
+ return 8;
+}
+
+void StubLayoutX86::setStubAddress(void *stub_, void *addr) {
+ uint8_t *stub = (uint8_t *)stub_;
+ stub[0] = 0xE9; // 32-bit pc-relative jump.
+ void **target = (void **)(stub + 1);
+ *target = addr;
+}
+
+size_t StubLayoutX86_64::getUnitStubSize() const {
+ return 16;
+}
+
+void StubLayoutX86_64::setStubAddress(void *stub_, void *addr) {
+ // x86 doesn't have proper register/mem to store the jump destination
+ // use below instructions to jump to the specified address
+
+ // jmp *0x0(%rip); jump to the location which is stored in next instruction
+ // addr; this is not a real instruction, just an address
+ uint8_t *stub = (uint8_t*)stub_;
+ stub[0] = 0xff;
+ stub[1] = 0x25;
+ stub[2] = 0x0;
+ stub[3] = 0x0;
+ stub[4] = 0x0;
+ stub[5] = 0x0;
+ uint64_t *target = reinterpret_cast<uint64_t*>(stub + 6);
+ *target = reinterpret_cast<uint64_t>(addr);
+}
+