I'm adding a feature to my Linux debugger (I'm using Ptrace to manipulate the traced process as well as libbfd/libopcodes) to unwind the stack and determine if discrepancies exist between each CALL's allocated stack space and a statically derived local variable size, printing the address and local stack size of each frame along the way.My general methodology is to take the address in the base pointer (EBP/RBP), increment the pointer to should should contain the stored frame pointer, dereference that address, examine it with PTRACE_PEEKDATA and repeat until I dereference an address occupying an area outside the stack.I know how to check code/data segment registers, but ideally I'd like a method to check if I'm still inside the callstack even if the segmentation has been changed by W^X memory pages or an otherwise nonexecutable stack.In short, how can I check (in the general case) when I've moved outside the stack without triggering a general protection fault?(As as aside, I realize I'm operating on the assumption that checking an address's page segment is the ideal methodology here -- perhaps another simpler method exists to determine if an address is within the current process's stack space)
How can I check I've moved outside the stack without triggering a protection fault?
debuggers;linux;x86;callstack;segmentation
So, it is totally untested but here is the result of a few Internet browsing.First the stack base address is present in /proc/<pid>/maps, then it must be accessible from user-space at some point.I looked at the code of the pstack command which is printing the content of the stack of a running process. This code is getting the base address from a link_map structure and store it inside the field l_addr. This field is set inside the function readLinkMap():static void readLinkMap(int pid, ElfN_Addr base, struct link_map *lm,                         char *name, unsigned int namelen){  /* base address */  lm->l_addr = (ElfN_Addr) ptrace(PTRACE_PEEKDATA, pid,                                  base + offsetof(struct link_map,l_addr), 0);  /* next element of link map chain */  if (-1 != (long) lm->l_addr || !errno)    lm->l_next = (struct link_map *) ptrace(PTRACE_PEEKDATA, pid,                                            base + offsetof(struct link_map, l_next), 0);  if ((-1 == (long) lm->l_addr || -1 == (long) lm->l_next) && errno) {    perror(ptrace);    quit(can't read target.);  }  loadString(pid, base + offsetof(struct link_map, l_name), name, namelen);}I guess this is the right way to go. So, I would advise you to take a look at the code of the pstack command (the file is not very long) and to get inspiration from it because it does something extremely similar to what you want (at least if I understand what you said correctly).Hope this short note will help you a bit.