|
@@ -305,6 +305,25 @@ ENTRY(startup_64)
|
|
|
/* Set up the stack */
|
|
|
leaq boot_stack_end(%rbx), %rsp
|
|
|
|
|
|
+ /*
|
|
|
+ * paging_prepare() and cleanup_trampoline() below can have GOT
|
|
|
+ * references. Adjust the table with address we are running at.
|
|
|
+ *
|
|
|
+ * Zero RAX for adjust_got: the GOT was not adjusted before;
|
|
|
+ * there's no adjustment to undo.
|
|
|
+ */
|
|
|
+ xorq %rax, %rax
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Calculate the address the binary is loaded at and use it as
|
|
|
+ * a GOT adjustment.
|
|
|
+ */
|
|
|
+ call 1f
|
|
|
+1: popq %rdi
|
|
|
+ subq $1b, %rdi
|
|
|
+
|
|
|
+ call adjust_got
|
|
|
+
|
|
|
/*
|
|
|
* At this point we are in long mode with 4-level paging enabled,
|
|
|
* but we might want to enable 5-level paging or vice versa.
|
|
@@ -381,6 +400,21 @@ trampoline_return:
|
|
|
pushq $0
|
|
|
popfq
|
|
|
|
|
|
+ /*
|
|
|
+ * Previously we've adjusted the GOT with address the binary was
|
|
|
+ * loaded at. Now we need to re-adjust for relocation address.
|
|
|
+ *
|
|
|
+ * Calculate the address the binary is loaded at, so that we can
|
|
|
+ * undo the previous GOT adjustment.
|
|
|
+ */
|
|
|
+ call 1f
|
|
|
+1: popq %rax
|
|
|
+ subq $1b, %rax
|
|
|
+
|
|
|
+ /* The new adjustment is the relocation address */
|
|
|
+ movq %rbx, %rdi
|
|
|
+ call adjust_got
|
|
|
+
|
|
|
/*
|
|
|
* Copy the compressed kernel to the end of our buffer
|
|
|
* where decompression in place becomes safe.
|
|
@@ -481,19 +515,6 @@ relocated:
|
|
|
shrq $3, %rcx
|
|
|
rep stosq
|
|
|
|
|
|
-/*
|
|
|
- * Adjust our own GOT
|
|
|
- */
|
|
|
- leaq _got(%rip), %rdx
|
|
|
- leaq _egot(%rip), %rcx
|
|
|
-1:
|
|
|
- cmpq %rcx, %rdx
|
|
|
- jae 2f
|
|
|
- addq %rbx, (%rdx)
|
|
|
- addq $8, %rdx
|
|
|
- jmp 1b
|
|
|
-2:
|
|
|
-
|
|
|
/*
|
|
|
* Do the extraction, and jump to the new kernel..
|
|
|
*/
|
|
@@ -512,6 +533,27 @@ relocated:
|
|
|
*/
|
|
|
jmp *%rax
|
|
|
|
|
|
+/*
|
|
|
+ * Adjust the global offset table
|
|
|
+ *
|
|
|
+ * RAX is the previous adjustment of the table to undo (use 0 if it's the
|
|
|
+ * first time we touch GOT).
|
|
|
+ * RDI is the new adjustment to apply.
|
|
|
+ */
|
|
|
+adjust_got:
|
|
|
+ /* Walk through the GOT adding the address to the entries */
|
|
|
+ leaq _got(%rip), %rdx
|
|
|
+ leaq _egot(%rip), %rcx
|
|
|
+1:
|
|
|
+ cmpq %rcx, %rdx
|
|
|
+ jae 2f
|
|
|
+ subq %rax, (%rdx) /* Undo previous adjustment */
|
|
|
+ addq %rdi, (%rdx) /* Apply the new adjustment */
|
|
|
+ addq $8, %rdx
|
|
|
+ jmp 1b
|
|
|
+2:
|
|
|
+ ret
|
|
|
+
|
|
|
.code32
|
|
|
/*
|
|
|
* This is the 32-bit trampoline that will be copied over to low memory.
|