@@ -160,6 +160,102 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
160160 * in exit.c or in signal.c.
161161 */
162162
163+ struct pt_regs_offset {
164+ const char * name ;
165+ int offset ;
166+ };
167+
168+ #define REG_OFFSET_NAME (r ) {.name = #r, .offset = offsetof(struct pt_regs, r)}
169+ #define REG_OFFSET_END {.name = NULL, .offset = 0}
170+
171+ static const struct pt_regs_offset regoffset_table [] = {
172+ REG_OFFSET_NAME (sr ),
173+ REG_OFFSET_NAME (sp ),
174+ REG_OFFSET_NAME (gpr2 ),
175+ REG_OFFSET_NAME (gpr3 ),
176+ REG_OFFSET_NAME (gpr4 ),
177+ REG_OFFSET_NAME (gpr5 ),
178+ REG_OFFSET_NAME (gpr6 ),
179+ REG_OFFSET_NAME (gpr7 ),
180+ REG_OFFSET_NAME (gpr8 ),
181+ REG_OFFSET_NAME (gpr9 ),
182+ REG_OFFSET_NAME (gpr10 ),
183+ REG_OFFSET_NAME (gpr11 ),
184+ REG_OFFSET_NAME (gpr12 ),
185+ REG_OFFSET_NAME (gpr13 ),
186+ REG_OFFSET_NAME (gpr14 ),
187+ REG_OFFSET_NAME (gpr15 ),
188+ REG_OFFSET_NAME (gpr16 ),
189+ REG_OFFSET_NAME (gpr17 ),
190+ REG_OFFSET_NAME (gpr18 ),
191+ REG_OFFSET_NAME (gpr19 ),
192+ REG_OFFSET_NAME (gpr20 ),
193+ REG_OFFSET_NAME (gpr21 ),
194+ REG_OFFSET_NAME (gpr22 ),
195+ REG_OFFSET_NAME (gpr23 ),
196+ REG_OFFSET_NAME (gpr24 ),
197+ REG_OFFSET_NAME (gpr25 ),
198+ REG_OFFSET_NAME (gpr26 ),
199+ REG_OFFSET_NAME (gpr27 ),
200+ REG_OFFSET_NAME (gpr28 ),
201+ REG_OFFSET_NAME (gpr29 ),
202+ REG_OFFSET_NAME (gpr30 ),
203+ REG_OFFSET_NAME (gpr31 ),
204+ REG_OFFSET_NAME (pc ),
205+ REG_OFFSET_NAME (orig_gpr11 ),
206+ REG_OFFSET_END ,
207+ };
208+
209+ /**
210+ * regs_query_register_offset() - query register offset from its name
211+ * @name: the name of a register
212+ *
213+ * regs_query_register_offset() returns the offset of a register in struct
214+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
215+ */
216+ int regs_query_register_offset (const char * name )
217+ {
218+ const struct pt_regs_offset * roff ;
219+
220+ for (roff = regoffset_table ; roff -> name != NULL ; roff ++ )
221+ if (!strcmp (roff -> name , name ))
222+ return roff -> offset ;
223+ return - EINVAL ;
224+ }
225+
226+ /**
227+ * regs_within_kernel_stack() - check the address in the stack
228+ * @regs: pt_regs which contains kernel stack pointer.
229+ * @addr: address which is checked.
230+ *
231+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
232+ * If @addr is within the kernel stack, it returns true. If not, returns false.
233+ */
234+ static bool regs_within_kernel_stack (struct pt_regs * regs , unsigned long addr )
235+ {
236+ return (addr & ~(THREAD_SIZE - 1 )) ==
237+ (kernel_stack_pointer (regs ) & ~(THREAD_SIZE - 1 ));
238+ }
239+
240+ /**
241+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
242+ * @regs: pt_regs which contains kernel stack pointer.
243+ * @n: stack entry number.
244+ *
245+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
246+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
247+ * this returns 0.
248+ */
249+ unsigned long regs_get_kernel_stack_nth (struct pt_regs * regs , unsigned int n )
250+ {
251+ unsigned long * addr = (unsigned long * )kernel_stack_pointer (regs );
252+
253+ addr += n ;
254+ if (regs_within_kernel_stack (regs , (unsigned long )addr ))
255+ return * addr ;
256+ else
257+ return 0 ;
258+ }
163259
164260/*
165261 * Called by kernel/ptrace.c when detaching..
0 commit comments