2

I recently tried to imagine how stack memory is probably dealt with inside the Linux kernel but could not come up with anything solid. I know the kernel uses its own functions for dynamic memory management but I have no idea how it manages just normal C stack memory because after all, that can be implemented with normal C and compiled with normal GCC. As far as I have it, stack memory allocation is normally dealt with by a form of libc when dealing with operating systems and even on something like AVR. As far as I have it though the Linux kernel does not depend on libc?

I am not entirely sure how stack memory management is delegated to libc in the first place though as it appears to be a built in language feature. All that I can imagine is that it is somehow generically compiled (or implemented) so that a provider can be assigned either afterwards or possibly as part of the compilation process. Could someone please shed some light on this for me?

Gerharddc
  • 3,443
  • 8
  • 37
  • 75
  • When a new process starts, it has a user-space stack mapped into the process address space, and a kernel stack for use when it makes system calls. The stack pointer starts off pointing at the stack. libc is not involved in this *at all*. The posted answer is somewhat confusing, but it does seem to be right about ELF binaries being able to control what kind of stack setup they get: http://stackoverflow.com/questions/18278803/how-does-elf-file-format-defines-the-stack. The default is not to have such a section, and then you get a default stack at the kernel's default choice of virt address. – Peter Cordes Dec 31 '15 at 21:57

3 Answers3

0

stack memory is allocated (the whole stack) during the link step.

The stack memory is (normally) placed in the .stack segment (which is nothing more than an offset and length, with no contents).

The .startup code (usually a assembly function in some library, I'm not sure which library) finds the name of the .stack section within the loaded code, adds the length value to get the top address of the stack (stacks grow downward) and (amongst several other operations) sets the sp and bp registers.

When the OS is running (I.E. not in 'user' mode) it (typically) has its' own stack space and uses its' own values for the sp and bp registers.

The switching between the 'user' mode and 'privileged' mode and the swapping of register values is handled in the transitions between what you wrote and the code in the kernel.

Most of this kind of switching is handled in the wrapper functions in the libc library and the resulting control transitions through a table of jumps into kernel routines.

Note: other CPUs and OSs have differing details about how things are accomplished, but the results are very similar.

user3629249
  • 15,593
  • 1
  • 16
  • 17
  • I can't find .stack segment in modern linux. `% objdump -h /bin/cat` – Zang MingJie Dec 31 '15 at 09:00
  • perhaps you could read this stackoverflow question to find the answers you are looking for: – user3629249 Dec 31 '15 at 09:33
  • 2
    Saving/restoring registers, and swapping to a kernel stack, is *not* handled by libc. The kernel can't trust libc, because libc is just user-space code run by unprivileged processes! Also, it has to happen and work the same when you make a system call "directly" (with the `syscall` instruction in 64bit mode for example), even for toy executables that don't link any libraries. – Peter Cordes Dec 31 '15 at 21:51
  • 2
    stack memory is not "allocated" at link step, it's just storing a number marked for default stack size. stack memory is allocated when program loaded by OS, using the "stack size" parameter. – crazii Oct 24 '18 at 08:17
  • 1
    @crazii, The parameters for the allocation of the stack are set at link time. The actual memory allocation is handled at load time. Sorry if I misspoke – user3629249 Oct 25 '18 at 05:36
0

A stack can be any block of read/write memory. There is nothing special about a stack. An operating system creates a stack—i.e., it allocates the memory and assigns it location to the stack pointer register—because one is needed to start the a process, but it does not manage the stack.

In unix-land, running a program is a two step process. First, you clone the a parent process. Thus, the new process has the same stack setup as the parent.

Finally, you execute the program. The program load gets the desired stack size from the executable file which in turn gets the information from the linker (see the "stack" option for the ld command, for example).

After starting up, an application could call a system service to allocate pages of memory and have the stack pointer register reference that. Then that becomes the program stack.

Keep in mind that this all refers to the USER stack. The operating system maintains a KERNEL stack for each process that it uses for its own purposes.

user3344003
  • 18,590
  • 3
  • 22
  • 52
0

As far as I have it, stack memory allocation is normally dealt with by a form of libc …

This program illustrates that nothing from libc is used for stack memory allocation:

// compile with: gcc -nostdlib nolibc.c -o nolibc
_start()
{
    int a[9999];
    *a = 0;
    asm("   mov %0,%%ebx\n\
            mov $1,%%eax\n\
            int $128" : : "r" (*a));    // _exit(*a);
}

If the allocated stack space is exceeded, a fault occurs and the kernel's fault handler can allocate more space, unless there is a limit reached or a fixed size used.

Armali
  • 14,228
  • 13
  • 47
  • 141