summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-08-02 15:12:18 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-08-02 15:12:18 -0700
commit4af5740afdbd10fc4e8f9370d7b5ad49642c20e4 (patch)
tree0724810baa66a62e55c6fec5884308417daa6422
parent85b661e35d82cea3c5edd27f111cffbd4ee47f4b (diff)
downloadgem5-4af5740afdbd10fc4e8f9370d7b5ad49642c20e4.tar.xz
X86: Finally get the x86 initial stack frame right.
After very carefully reading through the Linux source, I'm pretty confident I now know -exactly- how the initial stack frame is constructed, filled, and aligned. --HG-- extra : convert_revision : 3c654ade7e458bdd5445026860f11175f383a65f
-rw-r--r--src/arch/x86/process.cc68
1 files changed, 34 insertions, 34 deletions
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index afe41cdeb..ce5828a1d 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -167,7 +167,7 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
filename = argv[0];
//We want 16 byte alignment
- Addr alignmentMask = ~mask(4);
+ uint64_t align = 16;
// load object file into target memory
objFile->loadSections(initVirtMem);
@@ -285,8 +285,8 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
//Figure out how big the initial stack needs to be
- // The unaccounted for 0 at the top of the stack
- int mysterious_size = intSize;
+ // A sentry NULL void pointer at the top of the stack.
+ int sentry_size = intSize;
//This is the name of the file which is present on the initial stack
//It's purpose is to let the user space linker examine the original file.
@@ -301,32 +301,19 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
}
int arg_data_size = 0;
for (int i = 0; i < argv.size(); ++i) {
- warn("Argv[%d] size is %d\n", i, argv[i].size() + 1);
arg_data_size += argv[i].size() + 1;
}
- //The auxiliary vector data needs to be padded so it's size is a multiple
- //of the alignment mask.
- int aux_padding =
- ((aux_data_size + ~alignmentMask) & alignmentMask) - aux_data_size;
-
//The info_block needs to be padded so it's size is a multiple of the
//alignment mask. Also, it appears that there needs to be at least some
//padding, so if the size is already a multiple, we need to increase it
//anyway.
- int info_block_size =
- (mysterious_size +
- file_name_size +
- env_data_size +
- arg_data_size +
- ~alignmentMask) & alignmentMask;
-
- int info_block_padding =
- info_block_size -
- mysterious_size -
- file_name_size -
- env_data_size -
- arg_data_size;
+ int base_info_block_size =
+ sentry_size + file_name_size + env_data_size + arg_data_size;
+
+ int info_block_size = roundUp(base_info_block_size, align);
+
+ int info_block_padding = info_block_size - base_info_block_size;
//Each auxilliary vector is two 8 byte words
int aux_array_size = intSize * 2 * (auxv.size() + 1);
@@ -336,17 +323,30 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
int argc_size = intSize;
- int space_needed =
- info_block_size +
- aux_data_size +
- aux_padding +
+ //Figure out the size of the contents of the actual initial frame
+ int frame_size =
aux_array_size +
envp_array_size +
argv_array_size +
argc_size;
+ //There needs to be padding after the auxiliary vector data so that the
+ //very bottom of the stack is aligned properly.
+ int partial_size = frame_size + aux_data_size;
+ warn("The partial size is %d.\n", partial_size);
+ int aligned_partial_size = roundUp(partial_size, align);
+ warn("The aligned partial size is %d.\n", aligned_partial_size);
+ int aux_padding = aligned_partial_size - partial_size;
+ warn("The padding is %d.\n", aux_padding);
+
+ int space_needed =
+ info_block_size +
+ aux_data_size +
+ aux_padding +
+ frame_size;
+
stack_min = stack_base - space_needed;
- stack_min &= alignmentMask;
+ stack_min = roundDown(stack_min, align);
stack_size = stack_base - stack_min;
// map memory
@@ -354,11 +354,11 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
roundUp(stack_size, pageSize));
// map out initial stack contents
- Addr mysterious_base = stack_base - mysterious_size;
- Addr file_name_base = mysterious_base - file_name_size;
+ Addr sentry_base = stack_base - sentry_size;
+ Addr file_name_base = sentry_base - file_name_size;
Addr env_data_base = file_name_base - env_data_size;
Addr arg_data_base = env_data_base - arg_data_size;
- Addr aux_data_base = arg_data_base - aux_data_size - info_block_padding;
+ Addr aux_data_base = arg_data_base - info_block_padding - aux_data_size;
Addr auxv_array_base = aux_data_base - aux_array_size - aux_padding;
Addr envp_array_base = auxv_array_base - envp_array_size;
Addr argv_array_base = envp_array_base - argv_array_size;
@@ -381,10 +381,10 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
uint64_t argc = argv.size();
uint64_t guestArgc = TheISA::htog(argc);
- //Write out the mysterious 0
- uint64_t mysterious_zero = 0;
- initVirtMem->writeBlob(mysterious_base,
- (uint8_t*)&mysterious_zero, mysterious_size);
+ //Write out the sentry void *
+ uint64_t sentry_NULL = 0;
+ initVirtMem->writeBlob(sentry_base,
+ (uint8_t*)&sentry_NULL, sentry_size);
//Write the file name
initVirtMem->writeString(file_name_base, filename.c_str());