SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /hwcore/cpu_context.c (Article 6.5) and /hwcore/cpu_context.c (Article 6)


001 /* Copyright (C) 2005  David Decotigny         !! 001 /* Copyright (C) 2000-2004, The KOS team
002    Copyright (C) 2000-2004, The KOS team       !! 002    Copyright (C) 1999  Free Software Foundation, Inc.
003                                                   003 
004    This program is free software; you can redi    004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU Genera    005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundatio    006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any lat    007    of the License, or (at your option) any later version.
008                                                   008    
009    This program is distributed in the hope tha    009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the     010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR    011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details    012    GNU General Public License for more details.
013                                                   013    
014    You should have received a copy of the GNU     014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to t    015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 3    016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA.                                           017    USA. 
018 */                                                018 */
019                                                   019 
020                                                   020 
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/klibc.h>                            022 #include <sos/klibc.h>
023 #include <drivers/bochs.h>                        023 #include <drivers/bochs.h>
024 #include <drivers/x86_videomem.h>                 024 #include <drivers/x86_videomem.h>
025 #include <hwcore/segment.h>                       025 #include <hwcore/segment.h>
026                                                   026 
027 #include "cpu_context.h"                          027 #include "cpu_context.h"
028                                                   028 
029                                                   029 
030 /**                                               030 /**
031  * Here is the definition of a CPU context for    031  * Here is the definition of a CPU context for IA32 processors. This
032  * is a SOS convention, not a specification gi    032  * is a SOS convention, not a specification given by the IA32
033  * spec. However there is a strong constraint     033  * spec. However there is a strong constraint related to the x86
034  * interrupt handling specification: the top o    034  * interrupt handling specification: the top of the stack MUST be
035  * compatible with the 'iret' instruction, ie     035  * compatible with the 'iret' instruction, ie there must be the
036  * err_code (might be 0), eip, cs and eflags o    036  * err_code (might be 0), eip, cs and eflags of the destination
037  * context in that order (see Intel x86 specs     037  * context in that order (see Intel x86 specs vol 3, figure 5-4).
038  *                                                038  *
039  * @note IMPORTANT: This definition MUST be co    039  * @note IMPORTANT: This definition MUST be consistent with the way
040  * the registers are stored on the stack in       040  * the registers are stored on the stack in
041  * irq_wrappers.S/exception_wrappers.S !!! Hen    041  * irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above.
042  */                                               042  */
043 struct sos_cpu_state {                         !! 043 struct sos_cpu_kstate {
044   /* (Lower addresses) */                         044   /* (Lower addresses) */
045                                                   045 
046   /* These are SOS convention */                  046   /* These are SOS convention */
047   sos_ui16_t  gs;                                 047   sos_ui16_t  gs;
048   sos_ui16_t  fs;                                 048   sos_ui16_t  fs;
049   sos_ui16_t  es;                                 049   sos_ui16_t  es;
050   sos_ui16_t  ds;                                 050   sos_ui16_t  ds;
051   sos_ui16_t  cpl0_ss; /* This is ALWAYS the S !! 051   sos_ui16_t  ss;
052                           Kernel context (CPL0 << 
053                           thread, even for a u << 
054   sos_ui16_t  alignment_padding; /* unused */     052   sos_ui16_t  alignment_padding; /* unused */
055   sos_ui32_t  eax;                                053   sos_ui32_t  eax;
056   sos_ui32_t  ebx;                                054   sos_ui32_t  ebx;
057   sos_ui32_t  ecx;                                055   sos_ui32_t  ecx;
058   sos_ui32_t  edx;                                056   sos_ui32_t  edx;
059   sos_ui32_t  esi;                                057   sos_ui32_t  esi;
060   sos_ui32_t  edi;                                058   sos_ui32_t  edi;
061   sos_ui32_t  ebp;                                059   sos_ui32_t  ebp;
062                                                   060 
063   /* MUST NEVER CHANGE (dependent on the IA32     061   /* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
064   sos_ui32_t  error_code;                         062   sos_ui32_t  error_code;
065   sos_vaddr_t eip;                                063   sos_vaddr_t eip;
066   sos_ui32_t  cs; /* 32bits according to the s !! 064   sos_ui32_t  cs;
067                      register is really 16bits << 
068   sos_ui32_t  eflags;                             065   sos_ui32_t  eflags;
069                                                   066 
070   /* (Higher addresses) */                        067   /* (Higher addresses) */
071 } __attribute__((packed));                        068 } __attribute__((packed));
072                                                   069 
073                                                   070 
074 /**                                            << 
075  * The CS value pushed on the stack by the CPU << 
076  * needed by the iret instruction, is 32bits l << 
077  * CS register is 16bits only: this macro simp << 
078  * "CS" register value from the CS value pushe << 
079  * CPU upon interrupt.                         << 
080  *                                             << 
081  * The remaining 16bits pushed by the CPU shou << 
082  * "reserved" and architecture dependent. IMHO << 
083  * anything about them. Considering that some  << 
084  * non-zero values for these 16bits (at least  << 
085  * ignore them.                                << 
086  */                                            << 
087 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_ << 
088   ( (pushed_ui32_cs_value) & 0xffff )          << 
089                                                << 
090                                                << 
091 /**                                            << 
092  * Structure of an interrupted Kernel thread's << 
093  */                                            << 
094 struct sos_cpu_kstate                          << 
095 {                                              << 
096   struct sos_cpu_state regs;                   << 
097 } __attribute__((packed));                     << 
098                                                << 
099                                                << 
100 /**                                            << 
101  * THE main operation of a kernel thread. This << 
102  * kernel thread function start_func and calls << 
103  * start_func returns.                         << 
104  */                                            << 
105 static void core_routine (sos_cpu_kstate_funct    071 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
106                           sos_ui32_t start_arg    072                           sos_ui32_t start_arg,
107                           sos_cpu_kstate_funct    073                           sos_cpu_kstate_function_arg1_t *exit_func,
108                           sos_ui32_t exit_arg)    074                           sos_ui32_t exit_arg)
109      __attribute__((noreturn));                   075      __attribute__((noreturn));
110                                                   076 
111 static void core_routine (sos_cpu_kstate_funct    077 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
112                           sos_ui32_t start_arg    078                           sos_ui32_t start_arg,
113                           sos_cpu_kstate_funct    079                           sos_cpu_kstate_function_arg1_t *exit_func,
114                           sos_ui32_t exit_arg)    080                           sos_ui32_t exit_arg)
115 {                                                 081 {
116   start_func(start_arg);                          082   start_func(start_arg);
117   exit_func(exit_arg);                            083   exit_func(exit_arg);
118                                                   084 
119   SOS_ASSERT_FATAL(! "The exit function of the    085   SOS_ASSERT_FATAL(! "The exit function of the thread should NOT return !");
120   for(;;);                                        086   for(;;);
121 }                                                 087 }
122                                                   088 
123                                                   089 
124 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_s !! 090 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_kstate **ctxt,
125                               sos_cpu_kstate_f    091                               sos_cpu_kstate_function_arg1_t *start_func,
126                               sos_ui32_t  star    092                               sos_ui32_t  start_arg,
127                               sos_vaddr_t stac    093                               sos_vaddr_t stack_bottom,
128                               sos_size_t  stac    094                               sos_size_t  stack_size,
129                               sos_cpu_kstate_f    095                               sos_cpu_kstate_function_arg1_t *exit_func,
130                               sos_ui32_t  exit    096                               sos_ui32_t  exit_arg)
131 {                                                 097 {
132   /* We are initializing a Kernel thread's con << 
133   struct sos_cpu_kstate *kctxt;                << 
134                                                << 
135   /* This is a critical internal function, so     098   /* This is a critical internal function, so that it is assumed that
136      the caller knows what he does: we legitim    099      the caller knows what he does: we legitimally assume that values
137      for ctxt, start_func, stack_* and exit_fu    100      for ctxt, start_func, stack_* and exit_func are allways VALID ! */
138                                                   101 
139   /* Setup the stack.                             102   /* Setup the stack.
140    *                                              103    *
141    * On x86, the stack goes downward. Each fra    104    * On x86, the stack goes downward. Each frame is configured this
142    * way (higher addresses first):                105    * way (higher addresses first):
143    *                                              106    *
144    *  - (optional unused space. As of gcc 3.3,    107    *  - (optional unused space. As of gcc 3.3, this space is 24 bytes)
145    *  - arg n                                     108    *  - arg n
146    *  - arg n-1                                   109    *  - arg n-1
147    *  - ...                                       110    *  - ...
148    *  - arg 1                                     111    *  - arg 1
149    *  - return instruction address: The addres    112    *  - return instruction address: The address the function returns to
150    *    once finished                             113    *    once finished
151    *  - local variables                           114    *  - local variables
152    *                                              115    *
153    * The remaining of the code should be read     116    * The remaining of the code should be read from the end upward to
154    * understand how the processor will handle     117    * understand how the processor will handle it.
155    */                                             118    */
156                                                   119 
157   sos_vaddr_t tmp_vaddr = stack_bottom + stack    120   sos_vaddr_t tmp_vaddr = stack_bottom + stack_size;
158   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;     121   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;
159                                                   122 
160   /* If needed, poison the stack */               123   /* If needed, poison the stack */
161 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS !! 124 #ifdef SOS_CPU_KSTATE_DETECT_UNINIT_VARS
162   memset((void*)stack_bottom, SOS_CPU_STATE_ST !! 125   memset((void*)stack_bottom, SOS_CPU_KSTATE_STACK_POISON, stack_size);
163 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STAC !! 126 #elif defined(SOS_CPU_KSTATE_DETECT_STACK_OVERFLOW)
164   sos_cpu_state_prepare_detect_kernel_stack_ov !! 127   sos_cpu_kstate_prepare_detect_stack_overflow(stack_bottom, stack_size);
165 #endif                                            128 #endif
166                                                   129 
167   /* Simulate a call to the core_routine() fun    130   /* Simulate a call to the core_routine() function: prepare its
168      arguments */                                 131      arguments */
169   *(--stack) = exit_arg;                          132   *(--stack) = exit_arg;
170   *(--stack) = (sos_ui32_t)exit_func;             133   *(--stack) = (sos_ui32_t)exit_func;
171   *(--stack) = start_arg;                         134   *(--stack) = start_arg;
172   *(--stack) = (sos_ui32_t)start_func;            135   *(--stack) = (sos_ui32_t)start_func;
173   *(--stack) = 0; /* Return address of core_ro    136   *(--stack) = 0; /* Return address of core_routine => force page fault */
174                                                   137 
175   /*                                              138   /*
176    * Setup the initial context structure, so t    139    * Setup the initial context structure, so that the CPU will execute
177    * the function core_routine() once this new    140    * the function core_routine() once this new context has been
178    * restored on CPU                              141    * restored on CPU
179    */                                             142    */
180                                                   143 
181   /* Compute the base address of the structure    144   /* Compute the base address of the structure, which must be located
182      below the previous elements */               145      below the previous elements */
183   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(s    146   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(struct sos_cpu_kstate);
184   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;   !! 147   *ctxt = (struct sos_cpu_kstate*)tmp_vaddr;
185                                                   148 
186   /* Initialize the CPU context structure */      149   /* Initialize the CPU context structure */
187   memset(kctxt, 0x0, sizeof(struct sos_cpu_kst !! 150   memset(*ctxt, 0x0, sizeof(struct sos_cpu_kstate));
188                                                   151 
189   /* Tell the CPU context structure that the f    152   /* Tell the CPU context structure that the first instruction to
190      execute will be that of the core_routine(    153      execute will be that of the core_routine() function */
191   kctxt->regs.eip = (sos_ui32_t)core_routine;  !! 154   (*ctxt)->eip = (sos_ui32_t)core_routine;
192                                                   155 
193   /* Setup the segment registers */               156   /* Setup the segment registers */
194   kctxt->regs.cs                               !! 157   (*ctxt)->cs  = SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KCODE); /* Code */
195     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO !! 158   (*ctxt)->ds  = SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA); /* Data */
196   kctxt->regs.ds                               !! 159   (*ctxt)->es  = SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA); /* Data */
197     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO !! 160   (*ctxt)->ss  = SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA); /* Stack */
198   kctxt->regs.es                               << 
199     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO << 
200   kctxt->regs.cpl0_ss                          << 
201     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO << 
202   /* fs and gs unused for the moment. */          161   /* fs and gs unused for the moment. */
203                                                   162 
204   /* The newly created context is initially in    163   /* The newly created context is initially interruptible */
205   kctxt->regs.eflags = (1 << 9); /* set IF bit !! 164   (*ctxt)->eflags = (1 << 9); /* set IF bit */
206                                                << 
207   /* Finally, update the generic kernel/user t << 
208   *ctxt = (struct sos_cpu_state*) kctxt;       << 
209                                                   165 
210   return SOS_OK;                                  166   return SOS_OK;
211 }                                                 167 }
212                                                   168 
213                                                   169 
214 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_ !! 170 #if defined(SOS_CPU_KSTATE_DETECT_STACK_OVERFLOW)
215 void                                              171 void
216 sos_cpu_state_prepare_detect_kernel_stack_over !! 172 sos_cpu_kstate_prepare_detect_stack_overflow(const struct sos_cpu_kstate *ctxt,
217                                                !! 173                                              sos_vaddr_t stack_bottom,
218                                                !! 174                                              sos_size_t stack_size)
219 {                                                 175 {
220   sos_size_t poison_size = SOS_CPU_STATE_DETEC !! 176   sos_size_t poison_size = SOS_CPU_KSTATE_DETECT_STACK_OVERFLOW;
221   if (poison_size > stack_size)                   177   if (poison_size > stack_size)
222     poison_size = stack_size;                     178     poison_size = stack_size;
223                                                   179 
224   memset((void*)stack_bottom, SOS_CPU_STATE_ST !! 180   memset((void*)stack_bottom, SOS_CPU_KSTATE_STACK_POISON, poison_size);
225 }                                                 181 }
226                                                   182 
227                                                   183 
228 void                                              184 void
229 sos_cpu_state_detect_kernel_stack_overflow(con !! 185 sos_cpu_kstate_detect_stack_overflow(const struct sos_cpu_kstate *ctxt,
230                                            sos !! 186                                      sos_vaddr_t stack_bottom,
231                                            sos !! 187                                      sos_size_t stack_size)
232 {                                                 188 {
233   unsigned char *c;                               189   unsigned char *c;
234   int i;                                          190   int i;
235                                                   191 
236   /* On SOS, "ctxt" corresponds to the address << 
237      the saved context in Kernel mode (always, << 
238      context of a user thread). Here we make s << 
239      pointer is within the allowed stack area  << 
240   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stac    192   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stack_bottom);
241   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeo    193   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeof(struct sos_cpu_kstate)
242                    <= stack_bottom + stack_siz    194                    <= stack_bottom + stack_size);
243                                                << 
244   /* Check that the bottom of the stack has no << 
245   for (c = (unsigned char*) stack_bottom, i =     195   for (c = (unsigned char*) stack_bottom, i = 0 ;
246        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_ !! 196        (i < SOS_CPU_KSTATE_DETECT_STACK_OVERFLOW) && (i < stack_size) ;
247        c++, i++)                                  197        c++, i++)
248     {                                             198     {
249       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POI !! 199       SOS_ASSERT_FATAL(SOS_CPU_KSTATE_STACK_POISON == *c);
250     }                                             200     }
251 }                                                 201 }
252 #endif                                            202 #endif
253                                                   203 
254                                                   204 
255 /* =========================================== !! 205 sos_vaddr_t sos_cpu_kstate_get_PC(const struct sos_cpu_kstate *ctxt)
256  * Public Accessor functions                   << 
257  */                                            << 
258                                                << 
259                                                << 
260 sos_vaddr_t sos_cpu_context_get_PC(const struc << 
261 {                                                 206 {
262   SOS_ASSERT_FATAL(NULL != ctxt);                 207   SOS_ASSERT_FATAL(NULL != ctxt);
263                                                << 
264   /* This is the PC of the interrupted context << 
265      context). */                              << 
266   return ctxt->eip;                               208   return ctxt->eip;
267 }                                                 209 }
268                                                   210 
269                                                   211 
270 sos_vaddr_t sos_cpu_context_get_SP(const struc !! 212 sos_vaddr_t sos_cpu_kstate_get_SP(const struct sos_cpu_kstate *ctxt)
271 {                                                 213 {
272   SOS_ASSERT_FATAL(NULL != ctxt);                 214   SOS_ASSERT_FATAL(NULL != ctxt);
273                                                << 
274   /* On SOS, "ctxt" corresponds to the address << 
275      the saved context in Kernel mode (always, << 
276      context of a user thread). */             << 
277   return (sos_vaddr_t)ctxt;                       215   return (sos_vaddr_t)ctxt;
278 }                                                 216 }
279                                                   217 
280                                                   218 
281 void sos_cpu_context_dump(const struct sos_cpu !! 219 void sos_cpu_kstate_dump(const struct sos_cpu_kstate *ctxt)
282 {                                                 220 {
283   char buf[128];                                  221   char buf[128];
284   snprintf(buf, sizeof(buf),                      222   snprintf(buf, sizeof(buf),
285            "CPU: eip=%x esp=%x eflags=%x cs=%x    223            "CPU: eip=%x esp=%x eflags=%x cs=%x ds=%x ss=%x err=%x",
286            (unsigned)ctxt->eip, (unsigned)ctxt    224            (unsigned)ctxt->eip, (unsigned)ctxt, (unsigned)ctxt->eflags,
287            (unsigned)GET_CPU_CS_REGISTER_VALUE !! 225            (unsigned)ctxt->cs, (unsigned)ctxt->ds, (unsigned)ctxt->ss,
288            (unsigned)ctxt->cpl0_ss,            << 
289            (unsigned)ctxt->error_code);           226            (unsigned)ctxt->error_code);
290   sos_bochs_putstring(buf); sos_bochs_putstrin    227   sos_bochs_putstring(buf); sos_bochs_putstring("\n");
291   sos_x86_videomem_putstring(23, 0,               228   sos_x86_videomem_putstring(23, 0,
292                           SOS_X86_VIDEO_FG_BLA    229                           SOS_X86_VIDEO_FG_BLACK | SOS_X86_VIDEO_BG_LTGRAY,
293                           buf);                   230                           buf);
294 }                                                 231 }
295                                                   232 
296                                                   233 
297 /* =========================================== !! 234 sos_ui32_t sos_cpu_kstate_get_EX_info(const struct sos_cpu_kstate *ctxt)
298  * Public Accessor functions TO BE USED ONLY B << 
299  */                                            << 
300                                                << 
301                                                << 
302 sos_ui32_t sos_cpu_context_get_EX_info(const s << 
303 {                                                 235 {
304   SOS_ASSERT_FATAL(NULL != ctxt);                 236   SOS_ASSERT_FATAL(NULL != ctxt);
305   return ctxt->error_code;                        237   return ctxt->error_code;
306 }                                                 238 }
307                                                   239 
308                                                   240 
309 sos_vaddr_t                                       241 sos_vaddr_t
310 sos_cpu_context_get_EX_faulting_vaddr(const st !! 242 sos_cpu_kstate_get_EX_faulting_vaddr(const struct sos_cpu_kstate *ctxt)
311 {                                                 243 {
312   sos_ui32_t cr2;                                 244   sos_ui32_t cr2;
313                                                   245 
314   /*                                           !! 246   /* See Intel Vol 3 (section 5.14): the address of the faulting
315    * See Intel Vol 3 (section 5.14): the addre !! 247      virtual address of a page fault is stored in the cr2 register */
316    * virtual address of a page fault is stored << 
317    * register.                                 << 
318    *                                           << 
319    * Actually, we do not store the cr2 registe << 
320    * kernel thread's context. So we retrieve t << 
321    * from the processor. The value we retrieve << 
322    * is actually the correct one because an ex << 
323    * with the code causing the fault, and cann << 
324    * the IDT entries in SOS are "interrupt gat << 
325    * disabled).                                << 
326    */                                          << 
327   asm volatile ("movl %%cr2, %0"                  248   asm volatile ("movl %%cr2, %0"
328                 :"=r"(cr2)                        249                 :"=r"(cr2)
329                 : );                              250                 : );
330                                                   251 
331   return cr2;                                     252   return cr2;
332 }                                                 253 }
333                                                   254 
334                                                   255 
335 /* =========================================== !! 256 sos_ui32_t sos_backtrace(const struct sos_cpu_kstate *cpu_kstate,
336  * Backtrace facility. To be used for DEBUGgin << 
337  */                                            << 
338                                                << 
339                                                << 
340 sos_ui32_t sos_backtrace(const struct sos_cpu_ << 
341                          sos_ui32_t max_depth,    257                          sos_ui32_t max_depth,
342                          sos_vaddr_t stack_bot    258                          sos_vaddr_t stack_bottom,
343                          sos_size_t stack_size    259                          sos_size_t stack_size,
344                          sos_backtrace_callbac    260                          sos_backtrace_callback_t * backtracer,
345                          void *custom_arg)        261                          void *custom_arg)
346 {                                                 262 {
347   int depth;                                      263   int depth;
348   sos_vaddr_t callee_PC, caller_frame;            264   sos_vaddr_t callee_PC, caller_frame;
349                                                   265 
350   /*                                              266   /*
351    * Layout of a frame on the x86 (compiler=gc    267    * Layout of a frame on the x86 (compiler=gcc):
352    *                                              268    *
353    * funcA calls funcB calls funcC                269    * funcA calls funcB calls funcC
354    *                                              270    *
355    *         ....                                 271    *         ....
356    *         funcB Argument 2                     272    *         funcB Argument 2
357    *         funcB Argument 1                     273    *         funcB Argument 1
358    *         funcA Return eip                     274    *         funcA Return eip
359    * frameB: funcA ebp (ie previous stack fram    275    * frameB: funcA ebp (ie previous stack frame)
360    *         ....                                 276    *         ....
361    *         (funcB local variables)              277    *         (funcB local variables)
362    *         ....                                 278    *         ....
363    *         funcC Argument 2                     279    *         funcC Argument 2
364    *         funcC Argument 1                     280    *         funcC Argument 1
365    *         funcB Return eip                     281    *         funcB Return eip
366    * frameC: funcB ebp (ie previous stack fram    282    * frameC: funcB ebp (ie previous stack frame == A0) <---- a frame address
367    *         ....                                 283    *         ....
368    *         (funcC local variables)              284    *         (funcC local variables)
369    *         ....                                 285    *         ....
370    *                                              286    *
371    * The presence of "ebp" on the stack depend    287    * The presence of "ebp" on the stack depends on 2 things:
372    *   + the compiler is gcc                      288    *   + the compiler is gcc
373    *   + the source is compiled WITHOUT the -f    289    *   + the source is compiled WITHOUT the -fomit-frame-pointer option
374    * In the absence of "ebp", chances are high    290    * In the absence of "ebp", chances are high that the value pushed
375    * at that address is outside the stack boun    291    * at that address is outside the stack boundaries, meaning that the
376    * function will return -SOS_ENOSUP.            292    * function will return -SOS_ENOSUP.
377    */                                             293    */
378                                                   294 
379   if (cpu_state)                               !! 295   if (cpu_kstate)
380     {                                             296     {
381       callee_PC    = cpu_state->eip;           !! 297       callee_PC    = cpu_kstate->eip;
382       caller_frame = cpu_state->ebp;           !! 298       caller_frame = cpu_kstate->ebp;
383     }                                             299     }
384   else                                            300   else
385     {                                             301     {
386       /* Skip the sos_backtrace() frame */        302       /* Skip the sos_backtrace() frame */
387       callee_PC    = (sos_vaddr_t)__builtin_re    303       callee_PC    = (sos_vaddr_t)__builtin_return_address(0);
388       caller_frame = (sos_vaddr_t)__builtin_fr    304       caller_frame = (sos_vaddr_t)__builtin_frame_address(1);
389     }                                             305     }
390                                                   306 
391   for(depth=0 ; depth < max_depth ; depth ++)     307   for(depth=0 ; depth < max_depth ; depth ++)
392     {                                             308     {
393       /* Call the callback */                     309       /* Call the callback */
394       backtracer(callee_PC, caller_frame + 8,     310       backtracer(callee_PC, caller_frame + 8, depth, custom_arg);
395                                                   311 
396       /* If the frame address is funky, don't     312       /* If the frame address is funky, don't go further */
397       if ( (caller_frame < stack_bottom)          313       if ( (caller_frame < stack_bottom)
398            || (caller_frame + 4 >= stack_botto    314            || (caller_frame + 4 >= stack_bottom + stack_size) )
399         return depth;                             315         return depth;
400                                                   316 
401       /* Go to caller frame */                    317       /* Go to caller frame */
402       callee_PC    = *((sos_vaddr_t*) (caller_    318       callee_PC    = *((sos_vaddr_t*) (caller_frame + 4));
403       caller_frame = *((sos_vaddr_t*) caller_f    319       caller_frame = *((sos_vaddr_t*) caller_frame);
404     }                                             320     }
405                                                   321   
406   return depth;                                   322   return depth;
407 }                                                 323 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]