From: Gabe Black Date: Thu, 2 Aug 2007 22:12:18 +0000 (-0700) Subject: X86: Finally get the x86 initial stack frame right. X-Git-Tag: m5_2.0_beta4~207 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4af5740afdbd10fc4e8f9370d7b5ad49642c20e4;p=gem5.git 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 --- 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());