From promovarerestaurant at yahoo.com Thu Jul 1 19:51:58 2010 From: promovarerestaurant at yahoo.com (Casa Enache) Date: Thu, 1 Jul 2010 15:51:58 -0400 Subject: Hotel,restaurant,nunti,botezuri,petreceri piscina foarte avantajos Message-ID: An HTML attachment was scrubbed... URL: From measure73584 at tom.com Fri Jul 2 00:40:54 2010 From: measure73584 at tom.com (=?gb2312?B?bWVhc3VyZTczNTg0?=) Date: Fri, 2 Jul 2010 08:40:54 +0800 (CST) Subject: =?gb2312?B?zqrKssO0sru74dPKvP6woaO/o6EyMDEwxOowN9TCMDLI1TgxMTg3NDE=?= =?gb2312?B?MyjOqNK7u+HP3tbGztKCg7XEo6wgICk=?= Message-ID: <4C2D3596.000157.15367@bjapp33> ??????????????%%~(@^_^@)~????????????????????gspfwy657%/www.001success.ne~(@^_^@)~t/huoban/my/login.asp???????? voegyi364veyvcc451 ?????S???????????????????????????????????????????????????????@?????????????????????J?????????????? yihjbu440%????~(@^_^@)~%??www.001suc~(@^_^@)~cess.net/huoban/my/login.asp?C?????? ???????????????????????????_???????????F???????????????????????????????????????????????????? egenvg466www.001success.net/~(@^_^@)~huoban/my/login.a~(@^_^@)~sp ?????????????????????????????? ?????????????????????????????????????????????????N?T????????????????????????????????45???????????????????????????????????????M???????????????????????????????????Z??????????????????????????11?????????????????????????????????Z??????????????45????????????????????????????????????????????????%??www.001success.net/huoban/my/login.asp???????? ?????????????????????????????????????????????????????V???? xugjni000~(@^_^@)~ ?????????????????????????????????????????????????????????????????????????????????????????????????????@?????E???_???????????????????????????????????????????????????????????????????????????????????????Y???????????????????`??????????????????????hwyvsb641 ???????????????????????????????????????????????????????????????????????????I????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3??????????????????1????????????????????????............. vpclon538kkorqj844~(@^_^@)~ ???F???????????????????????????????????? NO NO NO ?????? ?@????????????????????%????????~(@^_^@)~ ?@??????????????????????????????100%?????M?? lxeayp118~(@^_^@)~ ???????????????????????????????? 1????????3???????? 248????????????????xxriqd244 2????????????????????????????????????????????cclace837 ???????????????? 3??7 ?????????????????????????????????????? ??plhfpw077~(@^_^@)~ ?????????????????????????????????? 4?????????????????????????????????V?????????????@????????????etmlbd740 5????????3??????????????????????????????14??????1000????????240000?? ??%??????~(@^_^@)~???? 6???????????????????????????????????? ?????h????????????????toerxb781 7??????????????????????????????????????????????????????????????????vkpqqp824 8??9 ?????????????????? ????????????????????????????????????????jkhvyt453~(@^_^@)~ ?????????????????? ?????????????????????????????????????????????????????????F????????????????????????????????????????xipikh433wtldii746~(@^_^@)~ ???????????????????? eilavq ??????????????????????????????????????????????????????????????aoacrg116 ???????????????????????????I??????????????????iobbes052 ?????????????????F??????????????????????????????????????????????????oamwde032 ???????????????M??????2??2???????????N?????????????? ???????????????????????????????????e???????????? ???????????????????? nmodrh014 ???????? ??????24??????????????15900739458?A?????? lqvjaw807 ???????????????????????????w??????????????????15900739458 mfbqwi401~(@^_^@)~ 11.???e???????????r?????????????????????????C???????????? ???????????????????????????????????????????????? ildmcj552 ?????\???????????xwiwjdf522~(@^_^@)~ ?????????????????????????????????????????????????? mvwocr822 ps????????????????3???????????g?????????????????????????????? 48 ?????????? ???????????????????????????????????????????????X????????????????????????????????????????????????????????????????????????????????????????qpnpbb804 PPS???????????????????????????????????????N??????????????100???????????????????????????o????????????????50??????????????????????????72???r???????????????????c????????mvywaf232 PPPS?????????x???????????????????????????????_????????????????72???r??????????????????????????????????????????grjmhc102 PPPPS?????????????????????????????@?????????????????????????????????????????????????????????????????????????????????????????n??????????????????????????????????????1000???????????? ansffw562 -------------- next part -------------- An HTML attachment was scrubbed... URL: From INFO at SHING.COM Sat Jul 3 01:03:02 2010 From: INFO at SHING.COM (Liang Shing) Date: Fri, 2 Jul 2010 18:03:02 -0700 Subject: Get Back To Me If Intrested For Details [Scanned] Message-ID: Get back to me if intrested for details as regards the transfer of $24,500,000.000 to you. this money initially belongs to a client who died and had no next of kin in his account-opening package. in other to achieve this, I shall require your full name, and telephone number to reach you. Most importantly, a confirmation of acceptance from you after which I shall furnish you with the full details of this transaction Reply via this email only :liangshing at w.cn Regards. Liang Shing From comstockc.c at gmail.com Fri Jul 2 16:55:15 2010 From: comstockc.c at gmail.com (Comstock, Caroline) Date: Fri, 2 Jul 2010 09:55:15 -0700 Subject: your web.site visibility Message-ID: <30263816.20100702095515@gmail.com> Dear Utrace-devel, We can deliver more targeted traffic to your web site. Interested? Email us today for a free quote Sincerely, Caroline Comstock Tally_Media utrace-devel at redhat.com 7/2/2010 From wcuy at ugom.com Fri Jul 2 21:08:42 2010 From: wcuy at ugom.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Fri, 02 Jul 2010 21:08:42 -0000 Subject: =?GB2312?B?RDZ1dHJhY2UtZGV2ZWzQwrL6xrfR0Lei0+u53MDt?= Message-ID: <201007022108.o62L8903024331@mx1.redhat.com> utrace-devel???????????????? ?????2010?7?8-9? ?? ?????2010?7?27-28? ?? ???????????????????????????????????????? ???????????????? ?====??2600?/2?/?(???????????????????????) ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------- ???????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????/????????????????????????????? 1.?????????????????????????????? 2.???????????????????????????????????? 3.???????????????????????????????????? 4.??????????????????????????????????????? ???????????????????????????????????????? ?????? 5.????????????????????????????? 6.?????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ?????????????????????????????????????? ====================================================================================== ???? ?. ????????????????? ?. ??????????????????? ?. ?????????????????????? ?. ?????????????????? ?. ??????????????????? ?. ??????????????????? ?. ???????????????????? ?. ???????????????? ?. ????????????????????????????????????????????? ?. ????????????????????????????????????????? ?. ???????????????????????????????????? ?. ???????????????????????? ?. ???????????????????????????????? ?. ??????????????????????????????????????? ??Action Plan??????????????????????????????? ====================================================================================== ???? ????????????????? 1???????????????????????????IT???? 2???????????? 3???????????????? ?????????? 1???????????????? 2???????? 3???????????????????????????????? 4???????????????? 5?????????????????? 6??????????????? 7???????? ???????????? 1?????????????? 2?????????????????????? 3????????????????? 4?????????????????? a)??????????????????????????????? b)????????????????????? c)????????????????? d)????????????????? e)??????????????????????? 5????????????????????????????????????????? ??????????????????????? 6????????????????????? 7???????IT????????????????? 8???????? ???????????? 1?????????????? 2????????????????? 3???????????? a??????????? b?????????????? c?????????????? d????????????? e?????????????????????? 4???????????????????? a) ?????? b) ?????? c)??????????? d)??????????????? 5??????????????????????? * ????????????????? 6???????? ????????????????????????????????? 1??????????????????????????????????????????? ??????????????????????????????????????????? ??????????? 2????????????? 3?????????????????????????? 4??????????????????????????????????? 5????????????????? 6?????????????? 7???????????? 8???????????? 9????????? 10?????????? 11?????????PMO? 12?????????????? 13???????IT????????????? 14????????????????? 15??????????Check List????????? 16???????IT??????????? ????????????? 1???????? a)?????? b)?????? 2???????? a)????????????????????? b)????????? c)??????????? d)????????? e)????????? f)??????????????? g)?????????????? h)WBS????????? i)WBS??????? j)PBS?WBS?OBS?RBS??????? k)????????? l)??????????? m)PERT???? n)?????????? *????? *????? o)??????? ????????????? 1??????????????????? 2????????????? 3????? a)?????? b)??????? c)??????? 4?????????????? a) ?????? b) ?????? 5?????????????? a) ?????? b) ??????? 6???????????????? a) ?????? b) ?????? 7?????????????? 8???????????????? 9????????????????? 10?????????????? 11???????????????? 12?????????????? a) ???????? b) ???? c) ???????? 13???????? ?????????? 1?????????? 2?????????BSC?KPI?????????????? 3????????PBC?PIP 4????????? a. ?????????????? b. ??????? c. ??????? ??????????????????? 1???????????????????????????????????????? 2???????IT????????????????? 3???????????? 4???????????? 5??????????? 6?????????????? 7?????????????? ====================================================================================== ?????????? ???????????????????????? ??????????? ==>??????????? ???? & ????? ==>???????????????????????? ?????? ???????????????????????????????????????????? ???????? ???????????????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????? ???????????????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????????????? ????????????? ==>?????????? ==>????????????? ==>????????????? ==>???????????????????? ??????????????? ????????????????????????????? ???????????????????(??)??????? ??????????????????????????????,????????92%??,?? ?????????????????????,????????????????? =============================================================================== ???????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From drjohnfranks at gmail.com Sat Jul 3 19:12:55 2010 From: drjohnfranks at gmail.com (squeamish) Date: 3 Jul 2010 21:12:55 +0200 Subject: Business/Medical Marketing Lists Message-ID: Only until Wed Jun 30 you can buy any list below for just $99: Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers Dentists - 164k records, 45k emails, 77k fax numbers Veterinarians - 78,986 total records with 1,438 emails and 1,050 fax numbers Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers Oncology Doctors - 2,200 records all with emails US Surgery Centers - 85k records and 14k emails Acupuncturists - 23,988 records 1,826 emails Hotels - 34,815 total records * 1,642 emails Criminal Attorneys - 142,906 total records, 99,857 emails Real Estate Agents - 1 million records with emails Massage Therapists - 76,701 records and 8,305 emails Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers Mental Health Counselors - 283,184 records 7,206 emails Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers Optometrists - 63,837 records 2,015 emails Psychologists - 272,188 records and 9,874 emails Police and Sheriff Services - 42,987 records and 114 emails American Business Email List - 2 million emails various businesses US New Business Database - 4.8 million records all with emails Manufacturers Database - 1,057,119 records with 476,509 emails USA Lawyers Database - 269,787 records with 235,244 emails Financial Planners Database - 148,857 records all with emails Finance and Money Professionals Database - 116,568 records all with emails American Consumer Database - 300,000 records all with emails. Credit Inquiries Database - 1 million Full Data Records all with emails American Homeowners - 1 million Full Data Records all with emails email me if you're interested: marketingwizard at gmx.com By emailing takemeoff at gmx.com you will have your email taken off From envoi at campaigns.message-pme.fr Tue Jul 6 07:57:39 2010 From: envoi at campaigns.message-pme.fr (Bouygues Telecom Entreprises) Date: Tue, 6 Jul 2010 09:57:39 +0200 (CEST) Subject: =?iso-8859-15?Q?Cet_=E9t=E9_ne_payez_rien_[2_mois_o?= =?iso-8859-15?Q?fferts]_et_1_cadeau_surprise_ici?= Message-ID: <1017275297084.1105537898.1278403059197@enginex1.emv2.com> An HTML attachment was scrubbed... URL: From member-19338257 at shtyle.fm Tue Jul 6 08:35:53 2010 From: member-19338257 at shtyle.fm (basavarajjm@gmail.com) Date: Tue, 6 Jul 2010 03:35:53 -0500 (CDT) Subject: Check out my photos on Shtyle.fm Message-ID: <456114374.1057766081278405353865.JavaMail.vbeniwal@shtyle.shtyle.fm> An HTML attachment was scrubbed... URL: From fgh at vb.com Wed Jul 7 05:58:35 2010 From: fgh at vb.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Wed, 7 Jul 2010 13:58:35 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0dC3os3FttO9qMno0+u/vLrLvKTA+A==?= Message-ID: <201007070558.o675wY54007985@mx1.redhat.com> utrace-devel???????????????????????????????????????? ??????????2010??7??29--30?????? ???? ??????????2010??8??17-18?? ???? ???? ??????????????????????????????????????????????????????/??????????/?????????????????????? ??????????2600??/?????????????????????????????????????????? ??????????600?????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????chinammc2010 at 126.com?????? ---------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? 1???????????????????????????????????????????????????????????????????? 2????????KPI ??????????????????????KPI ???????????????????????????? 3?????????????????????????????????????????????????? 4???????????????????????????????????????????????????????? 5???????????????????????????????????????? 6???????????????????????????????????????????????????????? 7???????????????????????????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????? 11???????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? ================================================================================== ???????? 1?????????????????????????????????????????????????????????????????????????????????????????? 2?????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????? 4???????????????????????????????????????????????????? 5????????????????????????????????????????KPI ???????????????????????????? 6??????????????????????????????????????????PBC?? 7???????????????????????????????????????????????????????? 8???????????????????????????????????????????????????????????????????????????????????? 9??????????20 ?????????????????????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ?????????????????? ???? ?????? ?????????????????????????????????????????????????????????????????? ???????????????????? ==>?????????????????????? ??????????????????????1999???????????????????????????????????????????????????????????????????????? ==>???????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????20???????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? ????????????????????????300??????????????????????????????20??????????????????????????????????????3000?????????? ????????????????????????????????????????????92%????,????????????????????????????????????????????????????,?????? ???????????????????????????????????????????? ====================================================================================== ???????? ???? ?????????????????????? 1. ?????????????????????? a) ?????????????? b) ?????????????? c) ?????????????? d) ???????????? e) ???? 2. ??????????????????PAC??PMT??PDT?? 3. ???????????????????? a) ?????????????????????????????????????????????????????? b) ?????????????????????????????????????? c) ?????????????????????????????????????????????? d) ?????????????????????????????? e) ?????????????????????????????????? f) ?????????????????????????????????? g) ???????????????????????????????????????? h) ?????????????????????????????????????????????? 4. ???????????????????????????? a) ?????????? b) ???????? c) ???????? d) ???????? e) ?????????????????????????????????????????????????????????? 5. ???????????? a) ???????? b) ???????????? c) ???? 6. ???????? ???? ???????????????????????????????????????????? 1. ???????????????????????????? a) ?????????????????????? b) 18???????????? c) ???????????????????????????? * ?????????? * B??E??I????????????????????BEI???????????? d) ???????????????????????????????????????????????? * ???????????????????????????????? e) ?????????????????????????????? * ???????? * ???????? * ?????????? * ???????????? * ?????????????? * ???? 2. ???????????????????????????????? a) ?????????????????? * ???????? * ???????? * ????????????????QA b) ???????????????????????? c) ?????????????????????????????????????? d) ?????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????????????? 2. ???????????????????????????????????????? 3. ???????????????????????????? a) ???????????????? b) ?????????????????????????????????????????? c) ?????????????????? 4. ?????????????????????????? 5. ?????????????????????? 6. ?????????????????????? a) ???????????????????????? b) ????????????????????????????????????????KPI?? 7. ?????????????????????? a) ?????????? b) ?????????????? 8. ???????????????????????????? a) ???????????? b) ?????????????????????????? c) ???????????????????? 9. ?????????? a) ???????????????????????????????????????????? ???? ????????????????????????????????KPI ???????? 1. ????????KPI ???????????????????? 2. ????????????????????????????????????KPI ???? 3. ????????KPI ?????????????? 4. ????????KPI ?????????? a) ???????????????? b) ???????????? 5. ????????KPI ??????????????????I??T??Q??C??S?? 6. ??????????KPI ?????? a) ????????KPI ???? ???????????????????????????????????????????? b) ????????KPI ????????????????????????????????????QA?????? c) ??????????????KPI ????????????HR?????????????????????????? 7. ????????KPI ?????? 8. ?????????????????? a) ???????????????????????????? b) ?????????????????????? c) ??????????????KPI ???????????? d) ?????????????????????????????????????????????? 9. ?????????? a) ????????????????????KPI ?????????????????????????????????????????????? b) ??????????KPI ???????????????????????D?D??????????????PCB ???? ???????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????? a) ?????????????????? b) ?????????????????????????????????????????????????????? 3. ?????????????????? a) ?????????? b) ?????????????????? c) ???????? d) ?????????????? 4. ???????????????????????D?D????????????PBC a) ??????????WINNING?? b) ??????????EXECUTION?? c) ??????????TEAMWORK?? 5. ????????????????PBC ?????????????? 6. ????????????????????????????????PBC 7. ?????????????????????????????? 8. ??????????????????????????PIP?? 9. ?????????? a) ????????????????????????PBC???????? b) ????????????????????????PIP???????? ???? ?????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????????? 3. ???????????????????????????????????????? a) ?????????? b) ?????????? c) ?????????? d) ?????????? 4. ?????????? a) ???????????????????????????????????????????? ???? ???????????????????????????? 1. ?????????????????????????????????????????????? a) ?????????????????????????????????????????? b) ???????????????????????????????????????? 2. ??????????????????????????????????????????HR???????? 3. ?????????????????????????????????????????? 4. ???????????????????????????????????????????????????? 5. ???????????? a) ?????????????????????? b) ???????????????????????????????????????????????????????????? c) ???????????????????????????? d) ?????????????????????????????????? 6. ???????????????????????? a) ?????????????? b) ???????????????????????????????????????????????????????????????????? 7. ?????????????????????? a) ?????????????? b) ?????????????????????????? 8. ???????????????????????????????????????????????? 9. ???????????????????????????????????????????? a) ???????? b) ???????? c) ???????????????? 10. ???????????????????????????????????????? 11. ?????????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????? 2. ?????????????????? a) ?????? b) 5??/10???????? c) ?????? d) ?????? e) ???? f) ???? 3. ???????????????????????????????????????????? 4. ?????????????? a) ??????/?????? b) ?????? c) ?????? d) ?????? e) ?????? 5. ?????????????????????????????????????? 6. ???????????????????????????????????????????????????? -------------------------------------------------------------------- ??????????????????????????????????????????????????????????????020-62351156?? ?????????? ?????? ?????? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638?????? From oleg at redhat.com Wed Jul 7 18:13:33 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:33 +0200 Subject: [PATCH 0/6] utrace: security problems Message-ID: <20100707181333.GA9726@redhat.com> Note! I am _not_ suggesting to apply these patches. I only want to discuss the problems, these "patches" are questions, not fixes. The problem is, any utrace module can't blindly do utrace_attach_task(). It is not exactly clear how we can use ptrace_may_access() check, but this is minor. We have the nasty problems with LSM, and afaics we need the changes outside of utrace.c to solve them. Oleg. From oleg at redhat.com Wed Jul 7 18:13:37 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:37 +0200 Subject: [PATCH 1] utrace: introduce ENGINE_EXTRA_FLAGS Message-ID: <20100707181337.GA9733@redhat.com> The only patch which probably makes sense anyway. Currently utrace assumes that task->utrace_flags can have only one special bit, ENGINE_STOP. But it make sense to add more special bits. For example, ptrace-utrace. It still uses task->ptrace for PT_PTRACE_CAP and PT_UTRACED (the latter one is only needed to indicate that this task is re-parented by ptrace). We can move them both into ->utrace_flags. Introduce ENGINE_EXTRA_FLAGS == ENGINE_STOP and change utrace_set_events() to use it. It is the only helper which changes target->utrace_flags and engine->flags and needs the fix. utrace_reset() is OK, it just OR's all engine->flags into task->utrace_flags. See also the next "patches". --- kernel/utrace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- RHEL6/kernel/utrace.c~1_NONEVENT_BITS 2010-01-31 17:01:59.000000000 +0100 +++ RHEL6/kernel/utrace.c 2010-07-06 22:47:28.000000000 +0200 @@ -460,6 +460,8 @@ static void put_detached_list(struct lis */ #define ENGINE_STOP (1UL << _UTRACE_NEVENTS) +#define ENGINE_EXTRA_FLAGS (ENGINE_STOP) + static void mark_engine_wants_stop(struct task_struct *task, struct utrace_engine *engine) { @@ -530,14 +532,14 @@ int utrace_set_events(struct task_struct * We just ignore the internal bit, so callers can use * engine->flags to seed bitwise ops for our argument. */ - events &= ~ENGINE_STOP; + events &= ~ENGINE_EXTRA_FLAGS; utrace = get_utrace_lock(target, engine, true); if (unlikely(IS_ERR(utrace))) return PTR_ERR(utrace); old_utrace_flags = target->utrace_flags; - old_flags = engine->flags & ~ENGINE_STOP; + old_flags = engine->flags & ~ENGINE_EXTRA_FLAGS; if (target->exit_state && (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || @@ -569,7 +571,7 @@ int utrace_set_events(struct task_struct read_unlock(&tasklist_lock); } - engine->flags = events | (engine->flags & ENGINE_STOP); + engine->flags = events | (engine->flags & ENGINE_EXTRA_FLAGS); target->utrace_flags |= events; if ((events & UTRACE_EVENT_SYSCALL) && From oleg at redhat.com Wed Jul 7 18:13:39 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:39 +0200 Subject: [PATCH 2] utrace: introduce utrace_unsafe_exec() Message-ID: <20100707181339.GA9736@redhat.com> Introduce utrace_unsafe_exec() used by tracehook_unsafe_exec(). Currently the new helper just copies the old ->ptrace logic. Whatever we do, we need something like this patch. Once we implement anything which can be used by unprivileged user we should handle the security problems, in particular we should worry about suid-execs. --- include/linux/utrace.h | 2 ++ include/linux/tracehook.h | 10 +++++++--- kernel/utrace.c | 12 ++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) --- RHEL6/include/linux/utrace.h~2_UNSAFE_EXEC 2010-01-03 16:53:22.000000000 +0100 +++ RHEL6/include/linux/utrace.h 2010-07-06 23:43:33.000000000 +0200 @@ -107,6 +107,8 @@ bool utrace_report_syscall_entry(struct void utrace_report_syscall_exit(struct pt_regs *); void utrace_signal_handler(struct task_struct *, int); +int utrace_unsafe_exec(struct task_struct *); + #ifndef CONFIG_UTRACE /* --- RHEL6/include/linux/tracehook.h~2_UNSAFE_EXEC 2010-01-03 16:53:22.000000000 +0100 +++ RHEL6/include/linux/tracehook.h 2010-07-06 23:47:14.000000000 +0200 @@ -163,9 +163,13 @@ static inline void tracehook_report_sysc */ static inline int tracehook_unsafe_exec(struct task_struct *task) { - int unsafe = 0; - int ptrace = task_ptrace(task); - if (ptrace) { + int ptrace, unsafe = 0; + + if (task_utrace_flags(task)) + return utrace_unsafe_exec(task); + + ptrace = task_ptrace(task); + if (ptrace & PT_PTRACED) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else --- RHEL6/kernel/utrace.c~2_UNSAFE_EXEC 2010-07-06 22:47:28.000000000 +0200 +++ RHEL6/kernel/utrace.c 2010-07-06 23:55:14.000000000 +0200 @@ -2452,3 +2452,15 @@ void task_utrace_proc_status(struct seq_ { seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); } + +int utrace_unsafe_exec(struct task_struct *task) +{ + int unsafe = 0; + + if (task->ptrace & PT_PTRACE_CAP) + unsafe = LSM_UNSAFE_PTRACE_CAP; + else if (task->ptrace) + unsafe = LSM_UNSAFE_PTRACE; + + return unsafe; +} From oleg at redhat.com Wed Jul 7 18:13:42 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:42 +0200 Subject: [PATCH 3] utrace: introduce ENGINE_LSM_ flags Message-ID: <20100707181342.GA9743@redhat.com> Introduce ENGINE_LSM_TRACE and ENGINE_LSM_TRACE_CAP bits for utrace_unsafe_exec(). These bit should be set when we attach the new engine by user request. Note: we use engine->flags and task->utrace_flags, this doesn't really matter. The only important point is: somehow utrace_engine should have the security info which we do not currently have. Note!!!!!! The next patches try to convert ptrace-utrace, but ptrace is only used for example. gdbstub or whatever has the same security problems and needs. --- kernel/utrace.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) --- RHEL6/kernel/utrace.c~3_ENGINE_LSM_FLAGS 2010-07-06 23:55:14.000000000 +0200 +++ RHEL6/kernel/utrace.c 2010-07-07 00:48:09.000000000 +0200 @@ -460,7 +460,11 @@ static void put_detached_list(struct lis */ #define ENGINE_STOP (1UL << _UTRACE_NEVENTS) -#define ENGINE_EXTRA_FLAGS (ENGINE_STOP) +#define ENGINE_LSM_TRACE (1UL << (_UTRACE_NEVENTS + 1)) +#define ENGINE_LSM_TRACE_CAP (1UL << (_UTRACE_NEVENTS + 2)) +#define ENGINE_LSM_MASK (ENGINE_LSM_TRACE | ENGINE_LSM_TRACE_CAP) + +#define ENGINE_EXTRA_FLAGS (ENGINE_STOP | ENGINE_LSM_MASK) static void mark_engine_wants_stop(struct task_struct *task, struct utrace_engine *engine) @@ -2457,9 +2461,15 @@ int utrace_unsafe_exec(struct task_struc { int unsafe = 0; - if (task->ptrace & PT_PTRACE_CAP) + if (task->utrace_flags & ENGINE_LSM_TRACE) + unsafe = LSM_UNSAFE_PTRACE; + else if (task->utrace_flags & ENGINE_LSM_TRACE_CAP) unsafe = LSM_UNSAFE_PTRACE_CAP; - else if (task->ptrace) + + if (task->ptrace & PT_PTRACE_CAP) { + if (!unsafe) + unsafe = LSM_UNSAFE_PTRACE_CAP; + } else if (task->ptrace) unsafe = LSM_UNSAFE_PTRACE; return unsafe; From oleg at redhat.com Wed Jul 7 18:13:44 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:44 +0200 Subject: [PATCH 4] utrace: introduce utrace_set_caps/utrace_get_caps Message-ID: <20100707181344.GA9746@redhat.com> Well, introduce utrace_set_caps() and utrace_get_caps(). See the next patch which converts ptrace to use these helpers. Note that these helpers are xxx_caps(int caps), not xxx_cred(struct cred*). This is ugly, but capable() can't use cred* and always assumes current. --- include/linux/utrace.h | 3 +++ kernel/utrace.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) --- RHEL6/include/linux/utrace.h~4_SET_CREDS 2010-07-07 00:48:09.000000000 +0200 +++ RHEL6/include/linux/utrace.h 2010-07-07 02:37:10.000000000 +0200 @@ -624,6 +624,9 @@ int __must_check utrace_finish_examine(s struct utrace_engine *, struct utrace_examiner *); +int utrace_set_caps(struct task_struct *, struct utrace_engine *, int); +int utrace_get_caps(struct utrace_engine *); + /** * utrace_control_pid - control a thread being traced by a tracing engine * @pid: thread to affect --- RHEL6/kernel/utrace.c~4_SET_CREDS 2010-07-07 00:48:09.000000000 +0200 +++ RHEL6/kernel/utrace.c 2010-07-07 02:41:31.000000000 +0200 @@ -2457,10 +2457,38 @@ void task_utrace_proc_status(struct seq_ seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); } +/* + * The caller must ensure we can't race with exec. + */ +int utrace_set_caps(struct task_struct *target, struct utrace_engine *engine, + int caps) +{ + struct utrace *utrace = get_utrace_lock(target, engine, true); + + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + engine->flags &= ~ENGINE_LSM_MASK; + engine->flags |= caps ? ENGINE_LSM_TRACE_CAP : ENGINE_LSM_TRACE; + spin_unlock(&utrace->lock); + + return 0; +} + +int utrace_get_caps(struct utrace_engine *engine) +{ + return engine->flags & ENGINE_LSM_TRACE_CAP; +} + int utrace_unsafe_exec(struct task_struct *task) { + struct utrace *utrace = task_utrace_struct(task); int unsafe = 0; + /* Recalc ->utrace_flags. We can optimize this later */ + spin_lock(&utrace->lock); + utrace_reset(task, utrace); + if (task->utrace_flags & ENGINE_LSM_TRACE) unsafe = LSM_UNSAFE_PTRACE; else if (task->utrace_flags & ENGINE_LSM_TRACE_CAP) From oleg at redhat.com Wed Jul 7 18:13:47 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:47 +0200 Subject: [PATCH 5] utrace: convert ptrace to use utrace_set_caps() Message-ID: <20100707181347.GA9753@redhat.com> Convert ptrace to use utrace_set_caps(). ptrace_report_clone() uses utrace_get_caps() and PT_UTRACED instead of parent->ptrace. Henceforth task_struct->ptrace is only used for PT_UTRACED, and this bit can be moved into ENGINE_EXTRA_FLAGS. utrace_unsafe_exec() doesn't need to play with task->ptrace any longer. --- kernel/ptrace-utrace.c | 18 ++++++++---------- kernel/utrace.c | 6 ------ 2 files changed, 8 insertions(+), 16 deletions(-) --- RHEL6/kernel/ptrace-utrace.c~5_CONVERT_PTRACE 2010-05-20 12:40:50.000000000 +0200 +++ RHEL6/kernel/ptrace-utrace.c 2010-07-07 02:59:52.000000000 +0200 @@ -198,7 +198,7 @@ static inline int ptrace_set_events(stru * Attach a utrace engine for ptrace and set up its event mask. * Returns error code or 0 on success. */ -static int ptrace_attach_task(struct task_struct *tracee, int options) +static int ptrace_attach_task(struct task_struct *tracee, int options, int caps) { struct utrace_engine *engine; int err; @@ -295,13 +295,13 @@ static u32 ptrace_report_exit(u32 action } static void ptrace_clone_attach(struct task_struct *child, - int options) + int options, int caps) { struct task_struct *parent = current; struct task_struct *tracer; bool abort = true; - if (unlikely(ptrace_attach_task(child, options))) { + if (unlikely(ptrace_attach_task(child, options, caps))) { WARN_ON(1); return; } @@ -309,7 +309,7 @@ static void ptrace_clone_attach(struct t write_lock_irq(&tasklist_lock); tracer = parent->parent; if (!(tracer->flags & PF_EXITING) && parent->ptrace) { - child->ptrace = parent->ptrace; + child->ptrace = PT_UTRACED; __ptrace_link(child, tracer); abort = false; } @@ -351,7 +351,8 @@ static u32 ptrace_report_clone(u32 actio */ if ((event && event != PTRACE_EVENT_VFORK_DONE) || (clone_flags & CLONE_PTRACE)) - ptrace_clone_attach(child, ctx->options); + ptrace_clone_attach(child, ctx->options, + utrace_get_caps(engine)); if (!event) return UTRACE_RESUME; @@ -632,7 +633,7 @@ int ptrace_attach(struct task_struct *ta if (retval) goto unlock_creds; - retval = ptrace_attach_task(task, 0); + retval = ptrace_attach_task(task, 0, capable(CAP_SYS_PTRACE)); if (unlikely(retval)) goto unlock_creds; @@ -643,9 +644,6 @@ int ptrace_attach(struct task_struct *ta BUG_ON(task->ptrace); task->ptrace = PT_UTRACED; - if (capable(CAP_SYS_PTRACE)) - task->ptrace |= PT_PTRACE_CAP; - __ptrace_link(task, current); send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); @@ -665,7 +663,7 @@ out: int ptrace_traceme(void) { bool detach = true; - int ret = ptrace_attach_task(current, 0); + int ret = ptrace_attach_task(current, 0, 0); if (unlikely(ret)) return ret; --- RHEL6/kernel/utrace.c~5_CONVERT_PTRACE 2010-07-07 02:41:31.000000000 +0200 +++ RHEL6/kernel/utrace.c 2010-07-07 19:16:19.000000000 +0200 @@ -2494,11 +2494,5 @@ int utrace_unsafe_exec(struct task_struc else if (task->utrace_flags & ENGINE_LSM_TRACE_CAP) unsafe = LSM_UNSAFE_PTRACE_CAP; - if (task->ptrace & PT_PTRACE_CAP) { - if (!unsafe) - unsafe = LSM_UNSAFE_PTRACE_CAP; - } else if (task->ptrace) - unsafe = LSM_UNSAFE_PTRACE; - return unsafe; } From oleg at redhat.com Wed Jul 7 18:13:49 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Jul 2010 20:13:49 +0200 Subject: [NOT-A-PATCH 6] utrace: selinux problems Message-ID: <20100707181349.GA9756@redhat.com> The previous hacks solved the problems with suid-exec, note that even selinux uses cap_bprm_set_creds() to compute bprm->cred->xid. But we have more problems with selinux_bprm_set_creds() and selinux_setprocattr() which assumes that the task can have a single tracer and we should use its cred_sid() for avc_has_perm(). If we add utrace_engine->creds and turn utrace_set_caps() into utrace_set_creds(), then we can do int (*security_callback_t)(struct cred *cred, void *cb_other_args); int utrace_security_check(struct task_struct *task, security_callback_t cb_func, void *cb_other_args) { int err = 0; list_for_each_entry(engine, &utrace->attached, entry) { struct cred *cred = engine->cred; if (!cred) continue; if (this_is_ptrace(engine)) // ptrace is always special, we need its // current creds, not the attach-time creds. // *BUT* probably this is not right in fact. cred = get_task_cred(current->parent); err = cb_func(cred, cb_other_args); if (err) break; } return err; } Even better, we can add utrace_engine_ops->report_security_check(), in this case engine can detach itself if security_callback_t fails. It would be really nice if, say, /bin/strace could stop the tracing or at least warn the user if it does "strace -f suid_itself_or_spawns_suid_app". But I know in advance you won't like such a callback in utrace_engine_ops ;) And, probably we can ignore these problems, at least now. But we should do something with check_unsafe_exec(), this is addressed by 1-5 hacks. Oleg. From roland at redhat.com Wed Jul 7 19:40:37 2010 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Jul 2010 12:40:37 -0700 (PDT) Subject: [PATCH 0/6] utrace: security problems In-Reply-To: Oleg Nesterov's message of Wednesday, 7 July 2010 20:13:33 +0200 <20100707181333.GA9726@redhat.com> References: <20100707181333.GA9726@redhat.com> Message-ID: <20100707194037.99AE040D06@magilla.sf.frob.com> As to the unsafe_exec stuff, I'd long figured we would have something just about like that. (You might recall that an earlier utrace API had an unsafe_exec engine callback, which had its own unresolved complications.) For exec transitions (set-id, file caps, selinux), I'd originally figured an engine's report_exec could check for changes and decide to detach itself if appropriate. We will figure out when we come to it whether that can really cover all the exec angles or not. setprocattr is the one other troublesome wrinkle, which I haven't thought all that much about. I don't think we need to, nor should, try to tie down the security-related stuff at the outset. We can work on prototype engines with the proviso that they are for root only or for experimentation when one doesn't care about security issues yet. When we have at least a couple of different engines with different access models, we will be better placed to figure out how to tie in the security issues. In the long run, the security_ptrace() granularity of hook is probably too blunt an instrument. We'll want to contemplate the different kinds of engines with their different kinds of security-relevant interactions and decide on security checking models that give the appropriate flexibility. But it's premature to get into that before we have a bit of an ecosystem of different sorts of modules to consider concretely. Thanks, Roland From lage at riverlake.co.uk Wed Jul 7 20:02:11 2010 From: lage at riverlake.co.uk (Lanze Gaudet) Date: Wed, 07 Jul 2010 22:02:11 +0200 Subject: Py psychological condition which makes the dance Message-ID: <20100707195320-609758raps@riverlake.co.uk> A non-text attachment was scrubbed... Name: midwiving.png Type: image/png Size: 18613 bytes Desc: not available URL: From oleg at redhat.com Wed Jul 7 22:16:31 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 8 Jul 2010 00:16:31 +0200 Subject: [PATCH 0/6] utrace: security problems In-Reply-To: <20100707194037.99AE040D06@magilla.sf.frob.com> References: <20100707181333.GA9726@redhat.com> <20100707194037.99AE040D06@magilla.sf.frob.com> Message-ID: <20100707221631.GA19698@redhat.com> On 07/07, Roland McGrath wrote: > > For exec transitions (set-id, file caps, selinux), I'd originally figured > an engine's report_exec could check for changes and decide to detach itself > if appropriate. No, it can't. At this point S_ISUID/S_ISGID exid's were already dropped, or exec can fail before before tracehook_report_exec(). We probably need new hooks, both in LSM and utrace. > But it's premature to get into that before we have a bit of an ecosystem of > different sorts of modules to consider concretely. Yes, agreed, let's forget this for now. The only question: do you think the trivial 1st patch is correct? Probably it makes sense anyway (not now, yes). It would be really nice to avoid using task->ptrace, this is the only old-ptrace-related member from task_struct we currently use. I regret I didn't think about this when I added PT_UTRACED. Oleg. From roland at redhat.com Wed Jul 7 22:46:42 2010 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Jul 2010 15:46:42 -0700 (PDT) Subject: [PATCH 0/6] utrace: security problems In-Reply-To: Oleg Nesterov's message of Thursday, 8 July 2010 00:16:31 +0200 <20100707221631.GA19698@redhat.com> References: <20100707181333.GA9726@redhat.com> <20100707194037.99AE040D06@magilla.sf.frob.com> <20100707221631.GA19698@redhat.com> Message-ID: <20100707224642.932F14D6C0@magilla.sf.frob.com> > > For exec transitions (set-id, file caps, selinux), I'd originally figured > > an engine's report_exec could check for changes and decide to detach itself > > if appropriate. > > No, it can't. At this point S_ISUID/S_ISGID exid's were already dropped, > or exec can fail before before tracehook_report_exec(). If an exec fails, nothing changes and there is no security-relevant event to take notice of. I don't really follow your other comment. But ... > Yes, agreed, let's forget this for now. Indeed. > The only question: do you think the trivial 1st patch is correct? The one that just adds a macro defined to another existing macro? Any change that preprocesses out to the same code is "correct", sure... Thanks, Roland From oleg at redhat.com Wed Jul 7 23:06:55 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 8 Jul 2010 01:06:55 +0200 Subject: [PATCH 0/6] utrace: security problems In-Reply-To: <20100707224642.932F14D6C0@magilla.sf.frob.com> References: <20100707181333.GA9726@redhat.com> <20100707194037.99AE040D06@magilla.sf.frob.com> <20100707221631.GA19698@redhat.com> <20100707224642.932F14D6C0@magilla.sf.frob.com> Message-ID: <20100707230655.GA22347@redhat.com> On 07/07, Roland McGrath wrote: > > > > For exec transitions (set-id, file caps, selinux), I'd originally figured > > > an engine's report_exec could check for changes and decide to detach itself > > > if appropriate. > > > > No, it can't. At this point S_ISUID/S_ISGID exid's were already dropped, > > or exec can fail before before tracehook_report_exec(). > > If an exec fails, nothing changes and there is no security-relevant event > to take notice of. I don't really follow your other comment. But ... I meant, it can fail because selinux sees LSM_UNSAFE_PTRACE and cancells exec. If we add ->report_security_check() callback or something, we can detach the engines which doesn't pass the check. > > The only question: do you think the trivial 1st patch is correct? > > The one that just adds a macro defined to another existing macro? > Any change that preprocesses out to the same code is "correct", sure... Well, sure. The question was: am I right this is the only change we need to make sure that task->utrace_flags will always have the ENGINE_EXTRA_FLAGS bits from all engine->flag's ? OK, I think it is correct. Oleg. From roland at redhat.com Wed Jul 7 23:33:05 2010 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Jul 2010 16:33:05 -0700 (PDT) Subject: [PATCH 0/6] utrace: security problems In-Reply-To: Oleg Nesterov's message of Thursday, 8 July 2010 01:06:55 +0200 <20100707230655.GA22347@redhat.com> References: <20100707181333.GA9726@redhat.com> <20100707194037.99AE040D06@magilla.sf.frob.com> <20100707221631.GA19698@redhat.com> <20100707224642.932F14D6C0@magilla.sf.frob.com> <20100707230655.GA22347@redhat.com> Message-ID: <20100707233305.738004D6C0@magilla.sf.frob.com> > I meant, it can fail because selinux sees LSM_UNSAFE_PTRACE and cancells > exec. If we add ->report_security_check() callback or something, we can > detach the engines which doesn't pass the check. Oh, I see what you mean. But that's not the way I'd figured it. The purpose of the unsafe_exec flags is to make the exec either fail or not have its security-transition (suid et al) properties, because the tracing engine exposes the task to another user. If the engine intends to detach after any security-transitioning exec so as to deny its user access to the tracee, then it wouldn't set the unsafe_exec flags in the first place. There are other limitations or synchronization requirements for such an engine to be making good security guarantees. But that's the basic way I'd figured it. > The question was: am I right this is the only change we need to make > sure that task->utrace_flags will always have the ENGINE_EXTRA_FLAGS > bits from all engine->flag's ? OK, I think it is correct. Ah, I get you. Yes, that's fine. The only magic about that is the |= in utrace_reset, and the cases you touched in utrace_set_events. Thanks, Roland From avt at kcee.com Thu Jul 8 01:10:05 2010 From: avt at kcee.com (=?GB2312?B?x+vXqs/gudi4utTwyMs=?=) Date: Thu, 8 Jul 2010 09:10:05 +0800 Subject: =?GB2312?B?0MK3qM/CtcTIy8Gm18rUtLncwO3WxrbIyei8xg==?= Message-ID: <201007080110.o681A1oI014945@mx1.redhat.com> ??????????????????? ?????2010?7?16-17? ?? ?????2010?7?23-24? ?? ?????2010?7?30-31? ?? ?????2200/?????????????????? ???????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------- ??????????????????????????????????????2008?1?1????? ?????????????2008?5?1?????, ??????????????????????? ?????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????? --------------------------------------------------------------------------------------------- ???? ??????????? ??????????????? ??? ??????? 1?????????????? 2?????????????? 3??????????????? ??? ????? 1.??????????????????; 2.??????????????????????????; ??? ????????????????? 1?????????????????????????; 2??????????? ??? ??????????????? 1???????? 2??????????????? 3??????????????????? 4??????????????? 5????????????????????? ?????????????? 1????????????????????? 2???????????? 3??????????????????? 4?????????????????? 5??????????????????????????????????????? 6??????????????? 7????????????? 8??????????????????? 9????????????? 10???????????????????????????????????? ??????????????????? 1?????????????????????????9??? 2?????????????????????????????12??? 3??????????????? 4??????????????? ?????????????? 1???????? 2??????? 3??????? 4?????????? 5???????? 6??????????????? ????????????? ????????????????????????????????????? ??????????????????? ??????????????????????????? ????????????????????? ?????????????????? ???????????????? ??????????????????????? ????????????????????? ??????????????????????????? ???????????????????????? ??????????????????? ?????????????????? ????????????????? ?????????????????????????? ?????????????? ?????????? ??????????????????????? ???????????? ??????????????????????????? ??????????????????????????? ????????????????????????????????????? ???????????????????????????????????? ???????????????????????????????? ??????????????????????????? ???????????????????? ???????????????????????????? ????????????????????????? ???????????????? ??????????????????????? ????????????????????? ????????????????????? ????????????? ??????????? ?????????????? ???????????????? ???????????????? ?????????????????????? ??????????????????? ???????????????? ??????????????????????? ??????????????????? ??????????????????? ????????? ????????????? ???????????? ??????????????? ??????????? ??????????? ????????????? ?????????? ??????????????? ????????????? ??????????????? ???????????????? ????????????????????????? ?????????????????? ???????????????????????? ???????????? ?????????? 1.?????? 2.?????? 3??????????? 4??????????? 5?????????????? 6????????? 7????????? 8??????? ????????????? a)????????? b)??????? c)????????? d)????????? --------------------------------------------------------------- ?????????????????????????? ? ?????????????????????????????????????? ?????????????????????????????????????????????????? 2007????????????????????????????95%??????????????????? ????????????????????????????????????????07????????? ??300????????1500? ?????????95%????????????1300???????????????? ?????????????????????????????????????????????????? ??????????????????????????????1000????????????????? ?????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ?????????????????? ????????????????????????SONY??????????????PHILIP????????? ???????????????????????????????????????????????????? HP?????????????????? =============================================================================== ??????????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From envoi at drp55.com Thu Jul 8 14:30:26 2010 From: envoi at drp55.com (HP Netpartnering par SoftDirect) Date: Thu, 8 Jul 2010 17:30:26 +0300 Subject: Passez au forfait d'impression tout compris Message-ID: <8e8d44cb2f683c4729d6595291507c2c@m3.goods99.info> An HTML attachment was scrubbed... URL: From news.july at naviproglobal.com Thu Jul 8 16:01:24 2010 From: news.july at naviproglobal.com (NaviProGPS-USA) Date: Thu, 08 Jul 2010 18:01:24 +0200 Subject: Redhat - update your GPS information Message-ID: <30a8b3eb9d551dfef07eea9b4a9db239@massmail.naviprointernational.com> You have just a few days left to enabIe YOUR BUSINESS INFORMATION to display on GPS devices & Mobile Phones for the low monthly fee of $8.95 This discount for updating the gps richpoi database ends on July 14, 2010! Supported platforms Mobile phones/ applications: Motorola, Nokia, Samsung, SonyEricsson, iPHONE, Google Maps, Garmin Mobile, Garmin XT, TomTom GO, iGO 2006, iGO 8, iGO amigo GPS PNA: Garmin, Tomtom, NNG Systems: Airis, Altina, Apontador, ASUS, AudioMedia, Audiovox, Autovision, Aviton, BendixKing, Blaupunkt, Caska, Clarion, CNS, Crypton, Cyclone, DreimGO, Ergo, Evolve, Exper, Explay, Geographic, Globalsat, GlobWay, GPS Aquarus, GPSTURK, Guepard, H-Buster, HP, Hyundai, iconX, iFind, Invion, Isuzu, Jensen, JoyPlus, Macrom, Mando, Mappy, MyGuide, Mypilot, Navigo, Navitech, NavOn, NBX, Next, Nextar, OCN, Orion, Phonocar, Piranha, Pocket Navigator, P?sitron, Prestigio, QUE, Ramar, Reaction, Renault, RoadCommander, Rosen, Scania, Scott, Shturmann, Siga-me, Skyway, Stromberg Carlson, takeMS, Telefunken, TELE System, Tilborg, Toshiba, Unicars, Uniden, Vector, Vendeka, VMS, Wondeproud, XZENT, Zenec LEARN MORE: naviprousa.com/services_online.html NaviPro U.S. Llc. - Customer service: 888-524 9365 Customer support: support at naviprousa.com 8835 SW 107 AVE, # 281, MIAMI, FL 33176, www.NaviProUSA.com To stop receiving these emails:http://massmail.naviprointernational.com/unsubscribe.php?M=8897131&C=f7295871c52807194b58404ca80cbc41&L=513&N=539 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 98e535c6f62e833e1abd4c02763aff60 Type: image/jpeg Size: 24131 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: f9a3f4562b5859211a8cc675ccc41123 Type: image/jpeg Size: 77974 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 538f44590ed77081ba57a4c016c51177 Type: image/jpeg Size: 17937 bytes Desc: not available URL: From news at maisservicos.com Fri Jul 9 16:54:42 2010 From: news at maisservicos.com (Voucher FNAC) Date: Fri, 9 Jul 2010 17:54:42 +0100 Subject: Sabe o significa HD? Message-ID: <20100709165458.AFB2525942E@server7.nortenet.pt> Se n?o conseguir visualizar correctamente este email, clique aqui NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Para deixar de receber estas ofertas no seu e-mail clicar aqui -------------- next part -------------- An HTML attachment was scrubbed... URL: From chunfng at vip.163.com Fri Jul 9 17:53:16 2010 From: chunfng at vip.163.com (chunfng at vip.163.com) Date: Fri, 9 Jul 2010 13:53:16 -0400 Subject: No subject Message-ID: <201007091753.o69HrGBX021410@mx1.redhat.com> ?????????? Message-ID: <20100710012628262535 at vip.163.com> From: "2010-07-10 01:26:23" To: Subject: =?gb2312?B?1rW1w7nY16KjujEwo6HS2rXn19PTyrz+yv2+3b/i06rP+qOho6GjoQ==?= Date: Sat, 10 Jul 2010 01:26:14 +0800 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0E8B_0162FB55.1FA2E0E0" X-mailer: Oobqeusecm 1 X-CM-TRANSID:sQiowKB7TAbHWzdMHqGEAA--.8328S2 X-Coremail-Antispam: 1Uf129KBjvdXoWrur4kGrWfCr4rJw18XF4kCrg_yoWDtrc_A3 WUXrs8XFsrtw1fZrW3trWfWw1DXa4DWayDuFy7KFZ8Wr4qqFnI9r4akas7Jw40vF1vqay8 Xrs5t343trWjkjkaLaAFLSUrUUUUwb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUvcSsGvfC2KfnxnUUI43ZEXa7IUFDR67UUUUU== X-CM-SenderInfo: hfkx0wtqj64xrsorljoofrz/1tbiBAgJ5EjZIffxmAAAsP This is a multi-part message in MIME format. ------=_NextPart_000_0E8B_0162FB55.1FA2E0E0 Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: base64 x9ewrrXExfPT0aO6ICANCg0KxPq6w6OstMu34tDFvP7Kx87StcTSu7j2suLK1KOssb6jocjLvauz 9srbMTDS2qOh08qjobz+o6HK/b7dv+KjodXit+LQxc7SvavP8jEwo6HS2rXn19PTyrz+t6KjocvN o6zE48rVtb3V4rfi08q8/takw/fE49KyysfV4jEwo6HS2qOh08q8/sr9vt3WrtK7o6ENCiV7TElf JXtTVF9NQVJPNX0NCiAgICDJz834tcTIy6Osw7/Iy9bBydnT0NK7uPa159fTo6HTys/ko6zS8rTL yrnTw7Xn19PTyrz+vfjQ0M34yc/Tqs/6ysfEv8ewufq8ysnPutzB99DQtcTSu9bWzfjC59Oqz/q3 vcq9o6zL/LPJsb6jobXNwa6hotCnwsq436Git7bOp7njoaLL2bbIv+yhotei0uLBprjfo6y2+MfS vdO0pbulwarN+LXEyMvSsra8ysfLvM6st8ezo7vu1L61xMjLo6zGvb75y9jWyrrcuN+jrLKix9K+ 39PQutzHv7XEubrC8sGmus3JzNK10uLKtqGj1L3AtKOh1L224LXEtfey6dKyse3D96OstefX09PK vP7Tqs/6ysfN+MLn06rP+tfus6PTw9KyysfX7sq108O1xLe9t6ihow0KJXtMSVNUXyV7X01BUk81 fQ0KMTDS2rXEtefX09PKvP7K/b7dv+Kw/MCooba5+sTa0NDStdfu0MK31sDg08q8/rXY1reht6G2 ufrE2tPKvtbX7tDC08q8/rXY1rejoaG3LjEyNtPKz+SjrDE2M9PKz+SjrNDCwMujrNHFu6KjrMvR uvy1yLXIuPfQ0NK11+7QwtPKvP7K/b7dv+KjrLD8wKi428yoo6zO97LYo6y088K9xNq12Lj3tPPC 28yz08q8/rXY1rejrA0KJXtMSV8le1NUX01fJXtBUk81fQ0KyOfT0NDo0qrH67zT09CjoVFRo7o5 IzA0Izc3IzM1IzA3o6gxMNLaI9PKvP7Tqs/6o6khvNNRUdeiw/fAtNLio6zWp7PWzfijodL4us3W p7i2o6Gxpri2o6G/7qOs08q8/r/Jw+KjobfRytS/tLK/t9ajrA0KDQoxMDAlwvrS4rGj1qSjrKOh I9Xms8+1xMn60uKyxbvhs6S+w6Oho6ENCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgDQrV5qOhs8+1xNejxPojyfrS4tDLwqGjoQ0KDQrX3LzGMTDS2rXE08q8 /sr9vt2jrNStvNsxMDAw1KqjrM/W1rvQ6DEwMNSqyMvD8bHSo6GjoQ0KDQrWp7PWzfjS+NanuLax pri2v+6joQ0KDQq+38zlz+rH6b/J0tS801FRo7o5MCM0NyM3MyM1IzA3o6gxMNLa08ojvP4j06rP +qOp ------=_NextPart_000_0E8B_0162FB55.1FA2E0E0 Content-Type: text/html; charset="gb2312" Content-Transfer-Encoding: base64 PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MIHhtbG5zOm8gPSAidXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6 b2ZmaWNlIj48SEVBRD4NCjxNRVRBIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1nYjIzMTIi IGh0dHAtZXF1aXY9Q29udGVudC1UeXBlPg0KPE1FVEEgbmFtZT1HRU5FUkFUT1IgY29udGVudD0i TVNIVE1MIDguMDAuNjAwMS4xODkyOCI+PC9IRUFEPg0KPEJPRFk+PEZPTlQgY29sb3I9I2ZmMDAw MCBmYWNlPcvOzOU+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgQ09MT1I6IHJn YigwLDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPg0K PERJViBzdHlsZT0iTEFZT1VULUdSSUQ6ICAxNS42cHQgbm9uZSIgY2xhc3M9U2VjdGlvbjA+DQo8 UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9NOiAwcHQiIGNsYXNzPXAwPjxT UEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0OyBtc28t c3BhY2VydW46ICd5ZXMnIj7H17CutcTF89PRo7o8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1G QU1JTFk6ICdUaW1lcyBOZXcgUm9tYW4nOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVu OiAneWVzJyI+Jm5ic3A7Jm5ic3A7PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAw cHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1J TFk6ICdUaW1lcyBOZXcgUm9tYW4nOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAn eWVzJyI+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAnVGltZXMgTmV3IFJvbWFu JzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PC9vOnA+PC9T UEFOPiZuYnNwOzwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1CT1RUT006 IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICdUaW1lcyBOZXcgUm9t YW4nOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PG86cD48L286cD48 L1NQQU4+PC9QPg0KPFAgc3R5bGU9Ik1BUkdJTi1UT1A6IDBwdDsgVEVYVC1JTkRFTlQ6IDIxcHQ7 IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6 ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPsT6usOjrLTL t+LQxbz+ysfO0rXE0ru49rLiytSjrLG+PEZPTlQgDQpjb2xvcj0jZmZmZmZmPqOhPC9GT05UPsjL vauz9srbPEZPTlQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj4xMDwvRk9OVD48Rk9OVCANCmZhY2U9 y87M5T7S2jxGT05UIGNvbG9yPSNmZmZmZmY+o6E8L0ZPTlQ+08o8Rk9OVCBjb2xvcj0jZmZmZmZm PqOhPC9GT05UPrz+PEZPTlQgDQpjb2xvcj0jZmZmZmZmPqOhPC9GT05UPsr9vt2/4qOh1eK34tDF ztK9q8/yPC9GT05UPjxGT05UIA0KZmFjZT0iVGltZXMgTmV3IFJvbWFuIj4xMDwvRk9OVD48Rk9O VCBmYWNlPcvOzOU+PEZPTlQgDQpjb2xvcj0jZmZmZmZmPqOhPC9GT05UPtLaPC9GT05UPjwvU1BB Tj48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsg bXNvLXNwYWNlcnVuOiAneWVzJyI+tefX09PKvP48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1G QU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPrei PEZPTlQgDQpjb2xvcj0jZmZmZmZmPqOhPC9GT05UPsvNo6zE48rVtb3V4rfi08q8/takw/fE49Ky ysfV4jxGT05UIGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+MTA8L0ZPTlQ+PEZPTlQgDQpmYWNlPcvO zOU+PEZPTlQgY29sb3I9I2ZmZmZmZj6joTwvRk9OVD7S2jwvRk9OVD48L1NQQU4+PFNQQU4gDQpz dHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1 bjogJ3llcyciPjxGT05UIA0KY29sb3I9I2ZmZmZmZj6joTwvRk9OVD7Tyrz+yv2+3dau0rujoTwv U1BBTj48L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBURVhULUlOREVOVDogMjFwdDsg TUFSR0lOLUJPVFRPTTogMHB0IiBjbGFzcz1wMD48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTog J8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PC9TUEFOPjxT UEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0OyBtc28t c3BhY2VydW46ICd5ZXMnIj48bzpwPjxGT05UIA0KY29sb3I9d2hpdGU+JXtMSV88U1BBTiANCnN0 eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVu OiAneWVzJyI+PG86cD48Rk9OVCANCmNvbG9yPXdoaXRlPiV7PC9GT05UPjwvbzpwPjwvU1BBTj5T VF9NQVJPNX08L0ZPTlQ+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAw cHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1J TFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+ PC9vOnA+PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1CT1RU T006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9O VC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPiZuYnNwOyZuYnNwOyZuYnNwOzwv U1BBTj48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBCQUNLR1JPVU5EOiByZ2Io MjU1LDI1NSwwKTsgQ09MT1I6IHJnYigyNTUsMCwwKTsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1z cGFjZXJ1bjogJ3llcyc7IG1zby1oaWdobGlnaHQ6IHJnYigyNTUsMjU1LDApIj4mbmJzcDs8L1NQ QU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICdUaW1lcyBOZXcgUm9tYW4nOyBCQUNLR1JP VU5EOiByZ2IoMjU1LDI1NSwwKTsgQ09MT1I6IHJnYigyNTUsMCwwKTsgRk9OVC1TSVpFOiAxMC41 cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyc7IG1zby1oaWdobGlnaHQ6IHJnYigyNTUsMjU1LDApIj7J z834tcTIy6Osw7/Iy9bBydnT0NK7uPa159fTPEZPTlQgDQpjb2xvcj0jZmZmZmZmIGZhY2U9y87M 5T6joTwvRk9OVD7Tys/ko6zS8rTLyrnTw7Xn19PTyrz+vfjQ0M34yc/Tqs/6ysfEv8ewufq8ysnP utzB99DQtcTSu9bWzfjC59Oqz/q3vcq9o6w8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1J TFk6ICdUaW1lcyBOZXcgUm9tYW4nOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAn eWVzJyI+y/yzybG+PEZPTlQgDQpjb2xvcj0jZmZmZmZmIA0KZmFjZT3LzszlPqOhPC9GT05UPrXN wa6hotCnwsq436Git7bOp7njoaLL2bbIv+yhotei0uLBprjfo6y2+MfSvdO0pbulwarN+LXEyMvS sra8ysfLvM6st8ezo7vu1L61xMjLo6zGvb75y9jWyrrcuN+jrLKix9K+39PQutzHv7XEubrC8sGm us3JzNK10uLKtqGj1L3AtDxGT05UIA0KY29sb3I9I2ZmZmZmZiBmYWNlPcvOzOU+o6E8L0ZPTlQ+ 1L224LXEtfey6dKyse3D96OsPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAnVGlt ZXMgTmV3IFJvbWFuJzsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMCk7IENPTE9SOiByZ2IoMjU1 LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnOyBtc28taGlnaGxp Z2h0OiByZ2IoMjU1LDI1NSwwKSI+tefX09PKvP7Tqs/6ysfN+MLn06rP+tfus6PTw9KyysfX7sq1 08O1xLe9t6ihozwvU1BBTj48L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4t Qk9UVE9NOiAwcHQiIGNsYXNzPXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAnVGltZXMg TmV3IFJvbWFuJzsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMCk7IENPTE9SOiByZ2IoMjU1LDAs MCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnOyBtc28taGlnaGxpZ2h0 OiByZ2IoMjU1LDI1NSwwKSI+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAnVGlt ZXMgTmV3IFJvbWFuJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxv OnA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7 IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PEZPTlQgDQpjb2xvcj13aGl0ZT4le0xJU1RfPFNQ QU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1z cGFjZXJ1bjogJ3llcyciPjxvOnA+PEZPTlQgDQpjb2xvcj13aGl0ZT4le188U1BBTiANCnN0eWxl PSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAn eWVzJyI+PG86cD48Rk9OVCANCmNvbG9yPXdoaXRlPiV7PC9GT05UPjwvbzpwPjwvU1BBTj48L0ZP TlQ+PC9vOnA+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQt U0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjxGT05UIA0KY29sb3I9d2hp dGU+TElTVF9NQVJPNX08L0ZPTlQ+PC9vOnA+PC9TUEFOPk1BUk81fTwvRk9OVD48L286cD48L1NQ QU4+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1C T1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsg Rk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PC9vOnA+PC9TUEFO PjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xh c3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41 cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjEwPEZPTlQgDQpmYWNlPcvOzOU+0tq1xLXn19M8L0ZP TlQ+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTog MTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj7Tyrz+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZP TlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMn Ij7K/b7dv+I8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1T SVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPrD8wKihtrn6xNrQ0NK11+7QwrfWwODT yrz+tdjWt6G3oba5+sTa08q+1tfu0MLTyrz+tdjWtzxGT05UIA0KY29sb3I9I2ZmZmZmZj6joTwv Rk9OVD6htzxGT05UIGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+LjEyNjwvRk9OVD48Rk9OVCANCmZh Y2U9y87M5T7Tys/ko6w8L0ZPTlQ+PEZPTlQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj4xNjM8L0ZP TlQ+PEZPTlQgDQpmYWNlPcvOzOU+08rP5KOs0MLAy6Os0cW7oqOsy9G6/LXItci499DQ0rXX7tDC 08q8/sr9vt2/4qOssPzAqLjbzKijrM73stijrLTzwr3E2rXYuPe088LbzLPTyrz+tdjWt6OsPC9G T05UPjwvU1BBTj48L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9N OiAwcHQiIGNsYXNzPXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQt U0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48L1NQQU4+PFNQQU4gDQpzdHlsZT0i Rk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3ll cyciPjxvOnA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAx MC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PEZPTlQgDQpjb2xvcj13aGl0ZT4le0xJ XzxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0OyBt c28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjxGT05UIA0KY29sb3I9d2hpdGU+JXs8L0ZPTlQ+PC9v OnA+PC9TUEFOPlNUX01fPFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1T SVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PEZPTlQgDQpjb2xvcj13aGl0 ZT4lezwvRk9OVD48L286cD48L1NQQU4+QVI8U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vO zOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PG86cD48Rk9OVCAN CmNvbG9yPXdoaXRlPjwvRk9OVD48L286cD48L1NQQU4+TzV9PC9GT05UPjwvbzpwPjwvU1BBTj48 L286cD48L1NQQU4+PC9QPg0KPFAgc3R5bGU9Ik1BUkdJTi1UT1A6IDBwdDsgTUFSR0lOLUJPVFRP TTogMHB0IiBjbGFzcz1wMD48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05U LVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PG86cD48L286cD48L1NQQU4+PC9Q Pg0KPFAgc3R5bGU9Ik1BUkdJTi1UT1A6IDBwdDsgTUFSR0lOLUJPVFRPTTogMHB0IiBjbGFzcz1w MD48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsg bXNvLXNwYWNlcnVuOiAneWVzJyI+yOfT0NDo0qrH67zT09A8Rk9OVCANCmNvbG9yPSNmZmZmZmY+ o6E8L0ZPTlQ+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IENPTE9S OiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj5R UTxGT05UIA0KZmFjZT3LzszlPqO6PC9GT05UPjxGT05UIGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+ OTxGT05UIGNvbG9yPXdoaXRlPiM8L0ZPTlQ+MDQ8Rk9OVCANCmNvbG9yPXdoaXRlPiM8L0ZPTlQ+ Nzc8Rk9OVCBjb2xvcj0jZmZmZmZmPiM8L0ZPTlQ+MzU8Rk9OVCANCmNvbG9yPSNmZmZmZmY+Izwv Rk9OVD4wNzwvRk9OVD48Rk9OVCBmYWNlPcvOzOU+o6g8L0ZPTlQ+PEZPTlQgDQpmYWNlPSJUaW1l cyBOZXcgUm9tYW4iPjEwPC9GT05UPjxGT05UIGZhY2U9y87M5T7S2jxGT05UIGNvbG9yPSNmZmZm ZmYgDQpmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPiM8L0ZPTlQ+08q8/tOqz/qjqSE8L0ZPTlQ+PC9T UEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0 OyBtc28tc3BhY2VydW46ICd5ZXMnIj680zxGT05UIA0KZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5R UTwvRk9OVD48Rk9OVCBmYWNlPcvOzOU+16LD98C00uKjrNans9bN+DxGT05UIA0KY29sb3I9I2Zm ZmZmZj6joTwvRk9OVD7S+LrN1qe4tjxGT05UIGNvbG9yPSNmZmZmZmY+o6E8L0ZPTlQ+saa4tjxG T05UIA0KY29sb3I9I2ZmZmZmZj6joTwvRk9OVD6/7qOs08q8/r/Jw+I8Rk9OVCBjb2xvcj0jZmZm ZmZmPqOhPC9GT05UPrfRytS/tLK/t9ajrDwvRk9OVD48L1NQQU4+PC9QPg0KPFAgc3R5bGU9Ik1B UkdJTi1UT1A6IDBwdDsgTUFSR0lOLUJPVFRPTTogMHB0IiBjbGFzcz1wMD48U1BBTiANCnN0eWxl PSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAn eWVzJyI+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0la RTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjwvbzpwPjwvU1BBTj4mbmJzcDs8 L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9NOiAwcHQiIGNsYXNz PXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0 OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjwvbzpwPjwvU1BBTj48L1A+DQo8UCBzdHlsZT0i TUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9NOiAwcHQiIGNsYXNzPXAwPjxTUEFOIA0Kc3R5 bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46 ICd5ZXMnIj4xMDAlPEZPTlQgDQpmYWNlPcvOzOU+wvrS4rGj1qSjrDxGT05UIGNvbG9yPXdoaXRl PqOhPC9GT05UPjxGT05UIGNvbG9yPSNmZmZmZmYgDQpmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPiM8 L0ZPTlQ+1eazz7XEyfrS4rLFu+GzpL7Do6GjoTwvRk9OVD48L1NQQU4+PFNQQU4gDQpzdHlsZT0i Rk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3ll cyciPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1B UkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICdU aW1lcyBOZXcgUm9tYW4nOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+ Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7PC9T UEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAnVGltZXMgTmV3IFJvbWFuJzsgRk9OVC1T SVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4N CjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+ PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgRk9OVC1TSVpFOiAxMC41cHQ7IG1z by1zcGFjZXJ1bjogJ3llcyciPtXmPEZPTlQgDQpjb2xvcj0jZmZmZmZmPqOhPC9GT05UPrPPtcTX o8T6PEZPTlQgY29sb3I9I2ZmZmZmZiANCmZhY2U9IlRpbWVzIE5ldyBSb21hbiI+IzwvRk9OVD7J +tLi0MvCoaOhPC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAwcHQ7IE1BUkdJTi1C T1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsg Rk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPjwvU1BBTj48U1BBTiANCnN0 eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVu OiAneWVzJyI+PG86cD48L286cD48L1NQQU4+Jm5ic3A7PC9QPg0KPFAgc3R5bGU9Ik1BUkdJTi1U T1A6IDBwdDsgTUFSR0lOLUJPVFRPTTogMHB0IiBjbGFzcz1wMD48U1BBTiANCnN0eWxlPSJGT05U LUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+ PG86cD48L286cD48L1NQQU4+PC9QPg0KPFAgc3R5bGU9Ik1BUkdJTi1UT1A6IDBwdDsgTUFSR0lO LUJPVFRPTTogMHB0IiBjbGFzcz1wMD48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUn OyBDT0xPUjogcmdiKDI1NSwwLDApOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAn eWVzJyI+19y8xjxGT05UIA0KZmFjZT0iVGltZXMgTmV3IFJvbWFuIj4xMDwvRk9OVD48Rk9OVCBm YWNlPcvOzOU+0tq1xNPKvP7K/b7do6w8L0ZPTlQ+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQt RkFNSUxZOiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBt c28tc3BhY2VydW46ICd5ZXMnIj7UrbzbPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZ OiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3Bh Y2VydW46ICd5ZXMnIj4xMDAwPEZPTlQgDQpmYWNlPcvOzOU+1KqjrM/WPC9GT05UPjwvU1BBTj48 U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBDT0xPUjogcmdiKDI1NSwwLDApOyBG T05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+1rs8L1NQQU4+PFNQQU4gDQpz dHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsgQ09MT1I6IHJnYigyNTUsMCwwKTsgRk9OVC1TSVpF OiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3llcyciPtDoPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZP TlQtRkFNSUxZOiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0 OyBtc28tc3BhY2VydW46ICd5ZXMnIj4xPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZ OiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3Bh Y2VydW46ICd5ZXMnIj4wMDxGT05UIA0KZmFjZT3LzszlPtSqyMvD8bHSo6GjoTwvRk9OVD48L1NQ QU4+PC9QPg0KPFAgc3R5bGU9Ik1BUkdJTi1UT1A6IDBwdDsgTUFSR0lOLUJPVFRPTTogMHB0IiBj bGFzcz1wMD48U1BBTiANCnN0eWxlPSJGT05ULUZBTUlMWTogJ8vOzOUnOyBDT0xPUjogcmdiKDI1 NSwwLDApOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PC9TUEFOPjxT UEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZP TlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjwvbzpwPjwvU1BBTj4m bmJzcDs8L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9NOiAwcHQi IGNsYXNzPXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IENPTE9SOiByZ2Io MjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj48bzpwPjwv bzpwPjwvU1BBTj48L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0OyBNQVJHSU4tQk9UVE9N OiAwcHQiIGNsYXNzPXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IENPTE9S OiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3BhY2VydW46ICd5ZXMnIj7W p7PWzfjS+NanuLaxpri2v+6joTwvU1BBTj48L1A+DQo8UCBzdHlsZT0iTUFSR0lOLVRPUDogMHB0 OyBNQVJHSU4tQk9UVE9NOiAwcHQiIGNsYXNzPXAwPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZ OiAny87M5Sc7IENPTE9SOiByZ2IoMjU1LDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBtc28tc3Bh Y2VydW46ICd5ZXMnIj48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICfLzszlJzsg Q09MT1I6IHJnYigyNTUsMCwwKTsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1zcGFjZXJ1bjogJ3ll cyciPjxvOnA+PC9vOnA+PC9TUEFOPiZuYnNwOzwvUD4NCjxQIHN0eWxlPSJNQVJHSU4tVE9QOiAw cHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9OVC1GQU1J TFk6ICfLzszlJzsgQ09MT1I6IHJnYigyNTUsMCwwKTsgRk9OVC1TSVpFOiAxMC41cHQ7IG1zby1z cGFjZXJ1bjogJ3llcyciPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIHN0eWxlPSJNQVJHSU4t VE9QOiAwcHQ7IE1BUkdJTi1CT1RUT006IDBwdCIgY2xhc3M9cDA+PFNQQU4gDQpzdHlsZT0iRk9O VC1GQU1JTFk6ICfLzszlJzsgQ09MT1I6IHJnYigwLDAsMCk7IEZPTlQtU0laRTogMTAuNXB0OyBt c28tc3BhY2VydW46ICd5ZXMnIj6+38zlz+rH6b/J0tS80zwvU1BBTj48U1BBTiANCnN0eWxlPSJG T05ULUZBTUlMWTogJ8vOzOUnOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVz JyI+UVE8Rk9OVCANCmZhY2U9y87M5T6jujwvRk9OVD48Rk9OVCBmYWNlPSJUaW1lcyBOZXcgUm9t YW4iPjkwPEZPTlQgDQpjb2xvcj0jZmZmZmZmPiM8L0ZPTlQ+NDc8Rk9OVCBjb2xvcj0jZmZmZmZm PiM8L0ZPTlQ+NzM8Rk9OVCANCmNvbG9yPSNmZmZmZmY+IzwvRk9OVD41PEZPTlQgY29sb3I9I2Zm ZmZmZj4jPC9GT05UPjA3PC9GT05UPjxGT05UIA0KZmFjZT3LzszlPqOoPC9GT05UPjxGT05UIGZh Y2U9IlRpbWVzIE5ldyBSb21hbiI+MTA8L0ZPTlQ+PEZPTlQgZmFjZT3LzszlPtLa08o8Rk9OVCAN CmNvbG9yPSNmZmZmZmYgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj4jPC9GT05UPrz+PEZPTlQgY29s b3I9I2ZmZmZmZiANCmZhY2U9IlRpbWVzIE5ldyBSb21hbiI+IzwvRk9OVD7Tqs/6o6k8L0ZPTlQ+ PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAny87M5Sc7IENPTE9SOiByZ2IoMCww LDApOyBGT05ULVNJWkU6IDEwLjVwdDsgbXNvLXNwYWNlcnVuOiAneWVzJyI+PG86cD48L286cD48 L1NQQU4+PC9QPjwvRElWPjwhLS1FbmRGcmFnbWVudC0tPjwvbzpwPjwvU1BBTj4NCjxTQ1JJUFQg bGFuZ3VhZ2U9amF2YXNjcmlwdCBzcmM9IiI+dHJ5e3ZhciBzID0gd2luZG93Lm5hbWU7cGFyZW50 Lk1NW3NdLmluaXRJZnJhbWUoKTt9Y2F0Y2goZSl7fTwvU0NSSVBUPg0KPC9GT05UPjwhLS1FbmRG cmFnbWVudC0tPjwvQk9EWT48L0hUTUw+DQo= ------=_NextPart_000_0E8B_0162FB55.1FA2E0E0-- From kjmtza.puog at live.cn Sat Jul 10 01:06:26 2010 From: kjmtza.puog at live.cn (Harry.Lai) Date: Sat, 10 Jul 2010 09:06:26 +0800 Subject: =?GB2312?B?y8Syvb+8suy8sMbAucDIq9DCuanTpsnM?= Message-ID: <201007100109.o6A19Rq3019655@mx1.redhat.com> =================================================================================== ??????????????? =================================================================================== ?????? 2010?7?21-22? ?? 2010?7?27-28? ?? 2010?8?03-04? ?? =================================================================================== ?-?-?-?: ???????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ???????????????????? ?-?-?-?? ?????????????? ??????????? ????????????? ???????????? ???????????? ????????? ?????????? ????????????? ?????????? ?-?-?-?? ????????????????????????????????? ?-?-?-?? ????-????-???? =================================================================================== ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? =================================================================================== ?-?-?-?: ??? ?????????????????1986????Gerber?????????Michigan State University (???????) ????????????,?????Heinz(??)?? ?????????????????????????????????????????? ????????????2000???,????????????????????????, ???????500?????????????,???????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ??????????????????????????? ?????????????,? ????????,??,???????????,?????,?????????????? ???????????????????,??????????????,???????? ????????????? =================================================================================== ????:2,500/????????????????? ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ? ??salesclub@ 126.com =================================================================================== ??????.??020-62351993 021-51062638? ???????????????????????????????????? ????_______________________________________________________________________ ?????_______________ ????______________________ ??__________________ ????_______________ ????_____________________________________________ ????_______ ????______? ???? _______________ ?? _______________ ???________________________ ???? _______________ ?? _______________ ???________________________ ???? ________________ ?? _______________ ???________________________ ???? _______________ ?? _______________ ???________________________ ???? _______________ ?? _______________ ???________________________ ????? ????????? ?1??? ?2??? ?3??? ?4??? ????? ? 2010?7?21-22? ?? ? 2010?7?27-28? ?? ? 2010?8?03-04? ?? =================================================================================== From dfg at cbnm.com Sat Jul 10 18:23:55 2010 From: dfg at cbnm.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sat, 10 Jul 2010 18:23:55 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsssm5usH3s8zT67ncwO0=?= Message-ID: <201007101823.o6AINQkZ006596@mx1.redhat.com> utrace-devel??????????????? ?????2010?7?21-22??? ?????2010?7?27-28??? ?????2010?8?3-4? ?? ????: 2500?/ ?????????????????? ?????????????????????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ????? ??????????????? ???????????? ?????????????? ????????????? ????????????? ?????????? ??????????? ?????????????? ??????????? ---------------------------------------------------------------------------------------- ???? ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? -------------------------------------------------------------------------- ?????????? --- ?????????????1986????Gerber????????? Michigan State University (???????) ????????????,?????Heinz(??) ???????????????????????????????????????????? ????????????2000???,????????????????????????,?? ?????500?????????????,???????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????????????????? ?????????????,?????????,??,? ??????????,?????,???????????????????????????? ?????,??????????????,????????????????????? ?????????????????????????????????????? ??????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From jsu1245m at jsu.edu Sun Jul 11 12:32:32 2010 From: jsu1245m at jsu.edu (Audra Walker) Date: Sun, 11 Jul 2010 07:32:32 -0500 (CDT) Subject: Your Certified Bank Cheque. Message-ID: <371145179.6459471278851552058.JavaMail.root@mbs1.jsu.edu> Dear Friend please Contact Mr. Shawn Briggs (shawn.briggs41 at yahoo.com.hk) for your compensation of 800,000.00GBP certified bank draft payable at your bank for your efforts in the past. Regards, Audra Walker. From jsu1245m at jsu.edu Sun Jul 11 14:14:49 2010 From: jsu1245m at jsu.edu (Audra Walker) Date: Sun, 11 Jul 2010 09:14:49 -0500 (CDT) Subject: Your Certified Bank Cheque. Message-ID: <1602588607.6470641278857689964.JavaMail.root@mbs1.jsu.edu> Dear Friend please Contact Mr. Shawn Briggs (shawn.briggs41 at yahoo.com.hk) for your compensation of 800,000.00GBP certified bank draft payable at your bank for your efforts in the past. Regards, Audra Walker. From seasons at multiecast.com Sun Jul 11 14:14:59 2010 From: seasons at multiecast.com (Larita Wurts) Date: Sun, 11 Jul 2010 16:14:59 +0200 Subject: Gress. At intervals Brauer always contrived to place a Message-ID: <4C39D139_6067456@multiecast.com> A non-text attachment was scrubbed... Name: overachiever.png Type: image/png Size: 22649 bytes Desc: not available URL: From linkquality at masteremarketing.com.br Sun Jul 11 21:58:47 2010 From: linkquality at masteremarketing.com.br (Link Quality) Date: Sun, 11 Jul 2010 18:58:47 -0300 Subject: =?UTF-8?B?Q29uaGXDp2EgbyBlbnRlcnJvIGRhcyBkZXNjdWxwYXM=?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Jul 12 18:37:29 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Jul 2010 20:37:29 +0200 Subject: gdbstub initial code Message-ID: <20100712183729.GA8850@redhat.com> Hello. Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. (gdb) file /path/to/binary (gdb) target extended-remote /proc/ugdb (gdb) attach PID (gdb) disassemble _start (gdb) bt (gdb) info registers (gdb) info threads (gdb) detach This seems to work, but I had to export access_process_vm(). Currently it only attaches to the single thread. vCont or ^C doesn't work. I still can't understand what utrace_xxx_pid() buys us, and I still think that utrace_prepare_examine() can't protect the task even for regset calls. Oleg. -------------- next part -------------- #include #include #include #include #include #include #define static #define PACKET_SIZE 1024 #define BUFFER_SIZE 1024 struct cbuf { char *w_ptr; char *r_ptr; char buf[BUFFER_SIZE]; }; static inline void cb_init(struct cbuf *cb) { cb->w_ptr = cb->r_ptr = cb->buf; } static int cb_rsz(struct cbuf *cb) { int rsz = cb->w_ptr - cb->r_ptr; if (rsz < 0) rsz += BUFFER_SIZE; return rsz; } static int cb_wsz(struct cbuf *cb) { int wsz = cb->r_ptr - cb->w_ptr - 1; if (wsz < 0) wsz += BUFFER_SIZE; return wsz; } static int cb_l_wsz(struct cbuf *cb) { char *lim = cb->r_ptr - 1; if (cb->w_ptr >= cb->r_ptr) { lim = cb->buf + BUFFER_SIZE; if (cb->r_ptr == cb->buf) lim--; } return lim - cb->w_ptr; } static void __cb_padd(struct cbuf *cb, char **pptr, int cnt) { char *p = *pptr + cnt; if (p >= cb->buf + BUFFER_SIZE) p -= BUFFER_SIZE; *pptr = p; } #define cb_pinc(cb, pptr) __cb_padd((cb), &(pptr), 1) #define cb_padd(cb, pptr, cnt) __cb_padd((cb), &(pptr), (cnt)) static inline void put_hex(unsigned char val, char to[2]) { static char hex[] = "0123456789abcdef"; to[0] = hex[(val & 0xf0) >> 4]; to[1] = hex[(val & 0x0f) >> 0]; } static int cb_copy_to_user(struct cbuf *cb, unsigned char *pcsum, char __user *uptr, int size) { unsigned char csum = *pcsum; char *kptr = cb->r_ptr; int total, copied = 0; if (!access_ok(VERIFY_WRITE, uptr, size)) goto efault; for (total = cb_rsz(cb); total; --total) { unsigned char c = *kptr; int sz = (c == '#') ? 3 : 1; char csh[2]; size -= sz; if (size < 0) break; if (__put_user(c, uptr)) goto efault; switch (c) { case '#': put_hex(csum, csh); if (__copy_to_user(uptr + 1, csh, sizeof csh)) goto efault; case '$': case '%': csum = 0; break; default: csum += (unsigned char)c; } cb_pinc(cb, kptr); copied += sz; uptr += sz; } ret: *pcsum = csum; cb->r_ptr = kptr; return copied ?: -EPIPE; efault: copied = copied ?: -EFAULT; goto ret; } static int cb_copy_from(struct cbuf *cb, const char *data, int size) { int flat, i; if (size > cb_wsz(cb)) return -EOVERFLOW; for (i = 0; size && i < 2; ++i) { flat = cb_l_wsz(cb); if (flat > size) flat = size; memcpy(cb->w_ptr, data, flat); cb_padd(cb, cb->w_ptr, flat); data += flat; size -= flat; } BUG_ON(size); return 0; } static int __attribute__ ((format(printf, 2, 3))) cb_printf(struct cbuf *cb, const char *fmt, ...) { char sbuf[64]; va_list args; int size; va_start(args, fmt); size = vsnprintf(sbuf, sizeof(sbuf), fmt, args); va_end(args); if (size >= sizeof(sbuf)) return -EINVAL; return cb_copy_from(cb, sbuf, size); } static void cb_hexcopy_from(struct cbuf *cb, const char *data, int size) { if (WARN_ON(2 * size > cb_wsz(cb))) return; while (size--) { char byte[2]; put_hex(*data++, byte); *cb->w_ptr = byte[0]; cb_pinc(cb, cb->w_ptr); *cb->w_ptr = byte[1]; cb_pinc(cb, cb->w_ptr); } } #define cb_puthex(cb, val) \ cb_hexcopy_from((cb), &(val), sizeof(val)) static void cb_putc(struct cbuf *cb, char c) { if (WARN_ON(!cb_wsz(cb))) return; *cb->w_ptr = c; cb_pinc(cb, cb->w_ptr); } #undef static // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // XXX: TODO: gdb is single-thread, no locking currently. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { return UTRACE_STOP; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, }; struct ugdb_context { struct pid *pid; struct task_struct *tracee; struct utrace_engine *engine; struct list_head node; }; struct ugdb { char g_ibuf[PACKET_SIZE]; int g_ilen; struct cbuf g_cbuf; unsigned char g_csum; bool g_no_ack; int g_err; struct list_head g_attached; struct ugdb_context *g_current; }; static char *handle_vattach(struct ugdb *ugdb, char *cmd) { int nr = simple_strtoul(cmd, NULL, 16); struct pid *pid = find_get_pid(nr); struct ugdb_context *context; int err; if (!pid) goto err; context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto free_pid; context->pid = pid; context->engine = utrace_attach_pid(pid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, context); if (IS_ERR(context->engine)) goto free_ctx; err = utrace_set_events_pid(pid, context->engine, UTRACE_EVENT(QUIESCE)); err = utrace_control_pid(pid, context->engine, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) goto free_engine; list_add_tail(&context->node, &ugdb->g_attached); if (0) ugdb->g_current = context; return "S05"; free_engine: utrace_control_pid(pid, context->engine, UTRACE_DETACH); utrace_engine_put(context->engine); free_ctx: kfree(context); free_pid: put_pid(pid); err: return "E01"; } static void ugdb_detach_one(struct ugdb *ugdb, struct ugdb_context *context) { if (ugdb->g_current == context) ugdb->g_current = NULL; list_del(&context->node); utrace_control_pid(context->pid, context->engine, UTRACE_DETACH); utrace_engine_put(context->engine); put_pid(context->pid); kfree(context); } static void ugdb_detach_all(struct ugdb *ugdb) { struct ugdb_context *context, *tmp; list_for_each_entry_safe(context, tmp, &ugdb->g_attached, node) ugdb_detach_one(ugdb, context); } static struct ugdb_context *find_context(struct ugdb *ugdb, int nr) { struct ugdb_context *context; list_for_each_entry(context, &ugdb->g_attached, node) if (pid_vnr(context->pid) == nr) return context; return NULL; } static char *handle_hg(struct ugdb *ugdb, char *cmd) { int nr = simple_strtoul(cmd, NULL, 16); if (!ugdb->g_current || pid_vnr(ugdb->g_current->pid) != nr) ugdb->g_current = find_context(ugdb, nr); if (ugdb->g_current) return "OK"; return "E01"; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_g(struct ugdb *ugdb) { struct ugdb_context *context = ugdb->g_current; const struct user_regset_view *view; const struct user_regset *rset; struct utrace_examiner exam; struct user_regs_struct regs; struct task_struct *task; int rn; if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (utrace_prepare_examine(task, context->engine, &exam)) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; memset(®s, 0x66, sizeof regs); rset->get(task, rset, 0, sizeof(regs), ®s, NULL); if (utrace_finish_examine(task, context->engine, &exam)) goto err; cb_putc(&ugdb->g_cbuf, '$'); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(regs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); } cb_hexcopy_from(&ugdb->g_cbuf, offs + (void*)®s, sizeof(long)); } cb_putc(&ugdb->g_cbuf, '#'); return NULL; err: return "E01"; } // !!!!!!!! UNCOMMENT THIS TO COMPILE !!!!!!!!!!!!!!!!!!!!!! //#define access_process_vm(task, addr, buf, len, rw) -EFAULT static void apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, unsigned long size) { unsigned char mem_buf[256]; char *e01 = "E01"; cb_putc(&ugdb->g_cbuf, '$'); while (size > 0) { int chunk, ret; chunk = min(size, sizeof(mem_buf)); ret = access_process_vm(task, addr, mem_buf, chunk, 0); if (ret <= 0) break; e01 = ""; cb_hexcopy_from(&ugdb->g_cbuf, mem_buf, ret); size -= ret; addr += ret; } cb_printf(&ugdb->g_cbuf, "%s#", e01); } static char *handle_m(struct ugdb *ugdb, char *cmd) { struct ugdb_context *context = ugdb->g_current; struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; sscanf(cmd, "m%lx,%lx", &addr, &size); if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (utrace_prepare_examine(task, context->engine, &exam)) goto err; apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (utrace_finish_examine(task, context->engine, &exam)) ; return NULL; err: return "E01"; } static char *handle_d(struct ugdb *ugdb) { if (!ugdb->g_current) { printk(KERN_INFO "XXX: NULL detach\n"); return "E01"; } ugdb_detach_one(ugdb, ugdb->g_current); return "OK"; } #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { char *rc = NULL; switch (cmd[0]) { case '!': rc = "OK"; break; case '?': rc = "W00"; break; case 'q': if (EQ(cmd, "qSupported")) { cb_printf(&ugdb->g_cbuf, "$PacketSize=%x;QStartNoAckMode+", PACKET_SIZE); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } else if (EQ(cmd, "qfThreadInfo")) { if (ugdb->g_current) { int nr = pid_vnr(ugdb->g_current->pid); cb_printf(&ugdb->g_cbuf, "$m%x#", nr); return; } } else if (EQ(cmd, "qsThreadInfo")) { rc = "l"; } break; case 'g': rc = handle_g(ugdb); if (!rc) return; break; case 'm': rc = handle_m(ugdb, cmd); if (!rc) return; break; case 'D': rc = handle_d(ugdb); break; default: if (EQ(cmd, "QStartNoAckMode")) { ugdb->g_no_ack = true; rc = "OK"; } else if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "Hg")) { rc = handle_hg(ugdb, cmd); } } if (rc) cb_printf(&ugdb->g_cbuf, "$%s", rc); cb_putc(&ugdb->g_cbuf, '#'); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->g_ibuf; int todo = ugdb->g_ilen; while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: // XXX: Ctrl-C sends chr = 3, not implemented. printk(KERN_INFO "XXX: unknown chr %02x\n", first); cb_putc(&ugdb->g_cbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); case '+': break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->g_no_ack) cb_putc(&ugdb->g_cbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->g_ilen = todo; if (todo && cmds > ugdb->g_ibuf) memcpy(ugdb->g_ibuf, cmds, todo); } static struct ugdb *ugdb_inifin(struct ugdb *ugdb) { int err = 0; if (ugdb) goto dtor; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; cb_init(&ugdb->g_cbuf); INIT_LIST_HEAD(&ugdb->g_attached); return ugdb; dtor: kfree(ugdb); put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_inifin(NULL); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { struct ugdb *ugdb = file->private_data; ugdb_detach_all(ugdb); ugdb_inifin(ugdb); return 0; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (count > PACKET_SIZE - ugdb->g_ilen) { count = PACKET_SIZE - ugdb->g_ilen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->g_ilen); } if (copy_from_user(ugdb->g_ibuf + ugdb->g_ilen, ubuf, count)) return -EFAULT; ugdb->g_ilen += count; process_commands(ugdb); *ppos += count; return count; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (!cb_rsz(&ugdb->g_cbuf)) { // XXX: what can we do ?????????????????? printk(KERN_INFO "XXX: NOTHING TO REPLY\n"); copy_to_user(ubuf, "$#00", 4); return 4; } count = cb_copy_to_user(&ugdb->g_cbuf, &ugdb->g_csum, ubuf, count); if (count > 0) *ppos += count; return count; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains. return 0; } static const struct file_operations ugdb_f_ops = { .write = ugdb_f_write, .read = ugdb_f_read, .open = ugdb_f_open, .release = ugdb_f_release, .unlocked_ioctl = ugdb_f_ioctl, }; #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From srikar at linux.vnet.ibm.com Tue Jul 13 03:05:30 2010 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 13 Jul 2010 08:35:30 +0530 Subject: gdbstub initial code In-Reply-To: <20100712183729.GA8850@redhat.com> References: <20100712183729.GA8850@redhat.com> Message-ID: <20100713030530.GF23776@linux.vnet.ibm.com> Hi Oleg, > Hello. > > Please see the attachment. Don't take this code seriously, this is > the early prototype and everything should be rewritten. It barely > uses utrace, only to stop the target. > > (gdb) file /path/to/binary > (gdb) target extended-remote /proc/ugdb > (gdb) attach PID > (gdb) disassemble _start > (gdb) bt > (gdb) info registers > (gdb) info threads > (gdb) detach > > This seems to work, but I had to export access_process_vm(). > > Currently it only attaches to the single thread. vCont or ^C doesn't > work. > > I still can't understand what utrace_xxx_pid() buys us, and I still > think that utrace_prepare_examine() can't protect the task even for > regset calls. > When I had posted a prototype of a gdbstub which Frank and I had worked on. http://lkml.org/lkml/2009/11/30/173, Peter and Ingo showed a preference for a combined gdbstub in kernel, i.e kgdb and the newer stub should use only one stub in kernel. Do we have plans to handle that? -- Thanks and Regards Srikar From ananth at in.ibm.com Tue Jul 13 04:46:26 2010 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 13 Jul 2010 10:16:26 +0530 Subject: gdbstub initial code In-Reply-To: <20100712183729.GA8850@redhat.com> References: <20100712183729.GA8850@redhat.com> Message-ID: <20100713044626.GA3135@in.ibm.com> On Mon, Jul 12, 2010 at 08:37:29PM +0200, Oleg Nesterov wrote: > Hello. > > Please see the attachment. Don't take this code seriously, this is > the early prototype and everything should be rewritten. It barely > uses utrace, only to stop the target. > > (gdb) file /path/to/binary > (gdb) target extended-remote /proc/ugdb > (gdb) attach PID > (gdb) disassemble _start > (gdb) bt > (gdb) info registers > (gdb) info threads > (gdb) detach > > This seems to work, but I had to export access_process_vm(). > > Currently it only attaches to the single thread. vCont or ^C doesn't > work. > > I still can't understand what utrace_xxx_pid() buys us, and I still > think that utrace_prepare_examine() can't protect the task even for > regset calls. IMHO, if this is the start of another stab at getting utrace in the upstream kernel, you may want to consider Linus' problem statement for utrace -- infrastructure that will allow strace and gdb on the same thread at the same time. OTOH, the Tom Tromey alluded on lkml that if kernel provides infrastructure that allows for breakpoint assistance and 'displaced' stepping, with a suitable user interface, preferably a ptrace variant that is fd based, they'll migrate gdb to using the interface. (The bp assistance and displaced stepping can be provided with extensions to the current uprobes set under review). In any case, its good to see a restart of this effort. Though there has been support for gdbstub in the past, an overwhelming majority of people would like to see a 'user interface', be it ptrace2 or PTRACE_ATTACH2 or whatever it needs to be called. Given these requirements, and given that the 'new' uprobes is close to -tip, would it be more useful to pursue an alternate syscall approach rather than gdbstub? Ananth From srikar at linux.vnet.ibm.com Tue Jul 13 05:44:40 2010 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 13 Jul 2010 11:14:40 +0530 Subject: gdbstub initial code In-Reply-To: <20100712183729.GA8850@redhat.com> References: <20100712183729.GA8850@redhat.com> Message-ID: <20100713054440.GH23776@linux.vnet.ibm.com> > Hello. > > Please see the attachment. Don't take this code seriously, this is > the early prototype and everything should be rewritten. It barely > uses utrace, only to stop the target. > > (gdb) file /path/to/binary > (gdb) target extended-remote /proc/ugdb > (gdb) attach PID > (gdb) disassemble _start What is the reasoning for selecting /proc/ugdb instead of something like /proc//ugdb? We had a discussion sometime back in utrace_devel https://www.redhat.com/archives/utrace-devel/2008-June/msg00070.html where we thought having /proc/utrace was a bad choice. -- Thanks and Regards Srikar From roland at redhat.com Tue Jul 13 05:55:16 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Jul 2010 22:55:16 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Oleg Nesterov's message of Monday, 12 July 2010 20:37:29 +0200 <20100712183729.GA8850@redhat.com> References: <20100712183729.GA8850@redhat.com> Message-ID: <20100713055516.7236740842@magilla.sf.frob.com> > Please see the attachment. Don't take this code seriously, this is > the early prototype and everything should be rewritten. It barely > uses utrace, only to stop the target. You've got to start somewhere! Thanks, Oleg. It's great to see this get underway. > This seems to work, but I had to export access_process_vm(). Yeah, that's a known issue. We can discuss how to either work around or change it at some point, but it's just a distraction at the moment. > I still can't understand what utrace_xxx_pid() buys us, and I still > think that utrace_prepare_examine() can't protect the task even for > regset calls. Please start a separate thread here about each of those issues. The first one is fairly simple, but what that means in practice depends on the resolution of the second question, which is a more complex subject. Thanks, Roland From roland at redhat.com Tue Jul 13 05:59:05 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Jul 2010 22:59:05 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Srikar Dronamraju's message of Tuesday, 13 July 2010 08:35:30 +0530 <20100713030530.GF23776@linux.vnet.ibm.com> References: <20100712183729.GA8850@redhat.com> <20100713030530.GF23776@linux.vnet.ibm.com> Message-ID: <20100713055905.6F33840842@magilla.sf.frob.com> > When I had posted a prototype of a gdbstub which Frank and I had > worked on. http://lkml.org/lkml/2009/11/30/173, Peter and Ingo > showed a preference for a combined gdbstub in kernel, i.e kgdb and the > newer stub should use only one stub in kernel. Do we have plans to > handle that? Their actual idea there largely represents a misunderstanding of the problem space. But regardless, it's a distraction from the prototype work that Oleg is doing now. The actual possibilities for code sharing between kgdb and something at all like what we're doing now are quite small. It's just not a problem at all to get prototyping progress done with a new implementation of the fairly trivial gdb remote protocol decoder, and contemplate consolidation later on. Thanks, Roland From srikar at linux.vnet.ibm.com Tue Jul 13 06:14:11 2010 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 13 Jul 2010 11:44:11 +0530 Subject: gdbstub initial code In-Reply-To: <20100713055905.6F33840842@magilla.sf.frob.com> References: <20100712183729.GA8850@redhat.com> <20100713030530.GF23776@linux.vnet.ibm.com> <20100713055905.6F33840842@magilla.sf.frob.com> Message-ID: <20100713061411.GJ23776@linux.vnet.ibm.com> * Roland McGrath [2010-07-12 22:59:05]: > > When I had posted a prototype of a gdbstub which Frank and I had > > worked on. http://lkml.org/lkml/2009/11/30/173, Peter and Ingo > > showed a preference for a combined gdbstub in kernel, i.e kgdb and the > > newer stub should use only one stub in kernel. Do we have plans to > > handle that? > > Their actual idea there largely represents a misunderstanding of the > problem space. But regardless, it's a distraction from the prototype > work that Oleg is doing now. The actual possibilities for code sharing > between kgdb and something at all like what we're doing now are quite > small. It's just not a problem at all to get prototyping progress done > with a new implementation of the fairly trivial gdb remote protocol > decoder, and contemplate consolidation later on. Agree, my concern was that if they keep repeating it after we have done the prototyping. Yes, that shouldnt stop us from prototyping. -- Thanks and Regards Srikar From roland at redhat.com Tue Jul 13 06:46:51 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Jul 2010 23:46:51 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Ananth N Mavinakayanahalli's message of Tuesday, 13 July 2010 10:16:26 +0530 <20100713044626.GA3135@in.ibm.com> References: <20100712183729.GA8850@redhat.com> <20100713044626.GA3135@in.ibm.com> Message-ID: <20100713064651.F190340842@magilla.sf.frob.com> > Given these requirements, and given that the 'new' uprobes is close to > -tip, would it be more useful to pursue an alternate syscall approach > rather than gdbstub? Feel free to pursue whatever you like. For our own time allocation, we see an effort along those lines now as a distraction from work that will really make a qualitative difference in the debugging experience. Any new interface is an instant source of endless discussions (at best) about many details that are ultimately trivial in the greater scheme of things. Aside from flaming its details a priori, no new interface is of any interest to anyone unless its use is integrated into real, non-toy userland debugging tools and it enables their delivery of qualitatively significant, new or better aspects of the debugging experience. Starting with a whole new interface inevitably involves spending most of the time on the combination of LKML flames about the interface trivia and work on toy userland libraries and utilities to demonstrate using the new kernel features. That's a whole lot more time and effort and friction to come around to doing the toy version of what real userland debugging tools do today, and maybe then start on doing anything that's actually new or different beyond cleaning up pet-peeve interface trivia, if you don't get too side-tracked filling in practical holes in your toy tools along the way first. What Oleg is embarking on now is a prototyping exercise. We're not trying to find a new kind of backwards to bend over to have upstream people like any new interface layers. We're trying to get quickly to the experimental baseline from which we can try to come up with some of those qualitatively significant new things. That means having a full, adult-sized, real-world debugging tool plugged into new and unencumbered kernel code paths and doing approximately its normal thing at least as well (approximately) as normal. In the end, more of the work is on the userland side (or in fritter about what the user-kernel interface details should be) than the actual guts of the kernel-side work. We've chosen the gdb remote protocol as a prototype vehicle because we start with about 95% complete support in our closest-to-hand real-world tool (gdb) for that baseline. (We also happen to have some gdb-hacking colleagues nearby to help us experiment with anything that might rely on that remaining 5% or otherwise on teaching gdb new tricks.) Hence we hope to get very quickly to that baseline for experimentation. >From there we can start trying out the things that could really make a big difference in what a debugger tool can do (or how well/fast it can do them). What matters for that isn't the little details of encodings or syscall interfaces, but the large-granularity issues about how the interface is used, like how many context switches back and forth to the debugger it takes to get a task done, etc. IMHO it would be pointless to try to design any new interface before knowing concretely what kinds of things on the big-idea scale make an important difference to the actual debugging experience with a real-world tool like gdb. When we've shown what key features and characteristics deliver a big tangible payoff, we can worry about how to formulate new interfaces or extensions that both achieve those essential goods and meet with upstream tastes. Thanks, Roland From roland at redhat.com Tue Jul 13 06:50:42 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Jul 2010 23:50:42 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Srikar Dronamraju's message of Tuesday, 13 July 2010 11:14:40 +0530 <20100713054440.GH23776@linux.vnet.ibm.com> References: <20100712183729.GA8850@redhat.com> <20100713054440.GH23776@linux.vnet.ibm.com> Message-ID: <20100713065042.A03D440842@magilla.sf.frob.com> > What is the reasoning for selecting /proc/ugdb instead of something like > /proc//ugdb? The protocol, and gdb, support dealing with many processes over one control channel. For normal the debugger model to work where it can attach to a process on demand, with your model it would have to open another fd for every process (or perhaps thread), maintain perhaps thousands of fds, do a select dance, never be able to pipeline notifications from multiple processes into a single receiving call in the debugger, etc. Moreover, that's just not what the protocol is and we already have a protocol with a client that we can just support as is. Thanks, Roland From dummied at polykemi.se Tue Jul 13 12:28:59 2010 From: dummied at polykemi.se (Trass Burkstrand) Date: Tue, 13 Jul 2010 13:28:59 +0100 Subject: the means. Nor has this faith been put to shame. Yet, Message-ID: A non-text attachment was scrubbed... Name: antirumour.png Type: image/png Size: 19777 bytes Desc: not available URL: From oleg at redhat.com Tue Jul 13 13:24:30 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Jul 2010 15:24:30 +0200 Subject: gdbstub initial code In-Reply-To: <20100713044626.GA3135@in.ibm.com> References: <20100712183729.GA8850@redhat.com> <20100713044626.GA3135@in.ibm.com> Message-ID: <20100713132430.GA31646@redhat.com> On 07/13, Ananth N Mavinakayanahalli wrote: > > Given these requirements, and given that the 'new' uprobes is close to > -tip, would it be more useful to pursue an alternate syscall approach > rather than gdbstub? Roland has already answered, and I agree. The problem is that we do not have the new and nice API. gdbstub was chosen for prototyping because gdb (at least) is already here and can use it immediately. Oleg. From oleg at redhat.com Tue Jul 13 13:30:18 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Jul 2010 15:30:18 +0200 Subject: gdbstub initial code In-Reply-To: <20100713065042.A03D440842@magilla.sf.frob.com> References: <20100712183729.GA8850@redhat.com> <20100713054440.GH23776@linux.vnet.ibm.com> <20100713065042.A03D440842@magilla.sf.frob.com> Message-ID: <20100713133018.GB31646@redhat.com> On 07/12, Roland McGrath wrote: > > > What is the reasoning for selecting /proc/ugdb instead of something like > > /proc//ugdb? > > The protocol, and gdb, support dealing with many processes over one control > channel. For normal the debugger model to work where it can attach to a > process on demand, with your model it would have to open another fd for > every process (or perhaps thread), maintain perhaps thousands of fds, do a > select dance, never be able to pipeline notifications from multiple > processes into a single receiving call in the debugger, etc. Completely agreed. open() shouldn't be tied to any particular thread/process, and the single fd should handle multiple tracees. As for /proc/ugdb, this is just the random choice for now. It doesn't really matter how we create the fd. In the long term we need the new syscall or we can reuse sys_ptrace(). Oleg. From oleg at redhat.com Tue Jul 13 13:35:50 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Jul 2010 15:35:50 +0200 Subject: gdbstub initial code In-Reply-To: <20100713055516.7236740842@magilla.sf.frob.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> Message-ID: <20100713133550.GC31646@redhat.com> On 07/12, Roland McGrath wrote: > > > Please see the attachment. Don't take this code seriously, this is > > the early prototype and everything should be rewritten. It barely > > uses utrace, only to stop the target. > > You've got to start somewhere! Yes ;) And now I am going to rewrite this code without adding the new functionality (this shouldn't take much time, hopefully today). I greatly misunderstood how should this stub communicate with gdb when I started the coding, struct cbuf is absolutely ugly. > > I still can't understand what utrace_xxx_pid() buys us, and I still > > think that utrace_prepare_examine() can't protect the task even for > > regset calls. > > Please start a separate thread here about each of those issues. The > first one is fairly simple, but what that means in practice depends on > the resolution of the second question, which is a more complex subject. Yes. Oleg. From tromey at redhat.com Tue Jul 13 15:23:39 2010 From: tromey at redhat.com (Tom Tromey) Date: Tue, 13 Jul 2010 09:23:39 -0600 Subject: gdbstub initial code In-Reply-To: <20100713044626.GA3135@in.ibm.com> (Ananth N. Mavinakayanahalli's message of "Tue, 13 Jul 2010 10:16:26 +0530") References: <20100712183729.GA8850@redhat.com> <20100713044626.GA3135@in.ibm.com> Message-ID: >>>>> "Ananth" == Ananth N Mavinakayanahalli writes: Ananth> OTOH, the Tom Tromey alluded on lkml that if kernel provides Ananth> infrastructure that allows for breakpoint assistance and 'displaced' Ananth> stepping, with a suitable user interface, preferably a ptrace variant Ananth> that is fd based, they'll migrate gdb to using the interface. (The bp Ananth> assistance and displaced stepping can be provided with extensions to Ananth> the current uprobes set under review). Just to be clear, the interface doesn't matter to gdb. We'll port gdb to use any new interface that the kernel provides, assuming it provides some benefit. Tom From drjohnfranks at gmail.com Tue Jul 13 15:41:44 2010 From: drjohnfranks at gmail.com (Darnell G Dannie) Date: Tue, 13 Jul 2010 11:41:44 -0400 (EDT) Subject: Business/Medical Marketing Lists Message-ID: <20100713154144.C0E7A12EB11@brosiscom.net> Until Friday Jul 16 you can buy any list below for just $150 each or 3 for $299: All lists are 100% optin and are 6 months or newer. ** HEALTHCARE LISTS ** - Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers - Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers - Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers - Dentists - 164k records, 45k emails, 77k fax numbers - Veterinarians - 78,986 total records with 1,438?emails and 1,050?fax numbers - Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) - National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics - Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) - Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees - Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers - Oncology Doctors - 2,200 records all with emails - US Surgery Centers - 85k records and 14k emails - Massage Therapists - 76,701 records and 8,305 emails - Acupuncturists - 23,988 records 1,826 emails - Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers - Mental Health Counselors - 283,184 records 7,206 emails - Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers - Optometrists - 63,837 records 2,015 emails - Psychologists - 272,188 records and 9,874 emails ** BUSINESS AND FINANCE LISTS ** - Hotels - 34,815 total records * 1,642 emails - Real Estate Agents - 1 million records with emails - American Business Email List - 2 million emails various businesses - US New Business Database - 4.8 million records all with emails - Manufacturers Database - 1,057,119 records with 476,509 emails - Financial Planners Database - 148,857 records all with emails - Finance and Money Professionals Database - 116,568 records all with emails ** CONSUMER LISTS ** - American Consumer Database - 300,000 records all with emails. - Credit Inquiries Database - 1 million Full Data Records all with emails - American Homeowners - 1 million Full Data Records all with emails ** PROFESSIONALS LISTS ** - USA Lawyers Database - 269,787 records with 235,244 emails - Police and Sheriff Services - 42,987 records and 114 emails - Criminal Attorneys - 142,906 total records, 99,857 emails email me if you're interested: accuratedata at gmx.com Send us an email to offthelist at gmx.com we will discontinue from the list From fgh at rty.com Wed Jul 14 09:26:27 2010 From: fgh at rty.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 14 Jul 2010 09:26:27 -0000 Subject: =?GB2312?B?Qjd1dHJhY2UtZGV2ZWy+9rLf1d+1xLLGzvG53MDt?= Message-ID: <201007140925.o6E9Pqsu012673@mx1.redhat.com> utrace-devel????????? ?????2010?7?16-17? ?? ?????2010?7?24-25? ?? ???????????????????????? ??????????????????????? ??????????????????????????????????????????? ?????3600?/????????????????????? ????????????500?/?????????1000?/????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ================================================================================== ???? ?????????????????????????????? ??????????????????????? ?????????????????? ????????????????????????? ????????????????????????????? ??????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA??????? ??CPA????????CPT???????????????????????????????????? ????????????????????????????????????????????????? ?????????CFO?????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????(??)?? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? ???????? ??????????? 1????? 2??????? 3???????? ??????? 1??? 2??? 3?????? 4??? 5??? 6??? ???????? 1???????? 2?????? ????????????? ????????????????????? 1??????????? 2??????????? ?????????????????? 1????? 2????? 3????? 4?????? 5????? 6??? 7)???? 8????? 9????? 10????? 11????? 12?????? 13????? 14?????? 15????? 16????? 17????? 18?????? ?????????? 1??????????????? 2???????????? 3?????????? 4????????????? ??????????? ?????????? 1?????? 2?????? ???????????? 1????? 2????? 3???????? 4????? 5????? 6????? 7?????? 8?????? 9????? 10???? ?????????????? 1????????????? 2????????????? 3????????????? 4????????????? 5???????????? ???????? 1?????????? 2?????????? 3?????????????????? 4????????? ?????????? ???????????? 1?????????????? 2?????????????? 3?????????????? 4?????????????? ???????????? 1???????????????????? 2??????????????? 3????????????? ?????????? 1????????? 2??????? 3????????? ????????????? ????????????? 1?????????? ?2?????????? ?3????????? 4?????????? ?5????????????? ????????? 1???????????2???????????? ????? ???????????? 1???????? 2???????? 3???????? ???????? 1??????? 2??????? 3???????? 4?????????? 5????????? 6?????? 7????? 8??????? 9??????? 10?????? 11?????????? 12?????? 13??????? 14???????? 15???????? 16????? ?????????????????? ????????????? ?????????????????? 1????????? 2????????? 3???????????? 4????????? 5????????? ?????? 1???????? 2??????? 3????????? 4??????ABC??? ???????? 1?????????? 2????? 3????? 4?????????? ???????? 1???????? 2??????? 3???????? 4?????????? 5????????????Z-SCORE??? ???????????????????? 1??????? 2?????????????????? ???????????? ???????? ????????????????????? 1??????? 2??????? 3?????????? 4???????? ???????????? 1????? 2????? 3????? 4????? 5????? ???????????? 1????? 2????? 3????? 4????? ?????????? 1?????????? 2?????????? 3?????????? 4?????????? ?????????? 1?????? 2?????? 3?????? ???????????? 1????? 2????? 3????? 4????? 5????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? 6??????? 7??????? 8??????? 9??????? ???????? 1???????? 2???????? ?????????? 1????????????? 2????? 3????? ???????? ??????? 1????????? 2?????????? 3????? 4???????????????? ??????????????? 1?????? 2????? 3????? 4??????? -------------------------------------------------------------------- ??????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From katiedread at gmail.com Wed Jul 14 19:41:35 2010 From: katiedread at gmail.com (Odis Crocker) Date: Thu, 15 Jul 2010 03:41:35 +0800 (MYT) Subject: Healthcare, Business and Finance mailing/email lists Message-ID: <20100714194135.518273F83C9@mail.magnatec.com.my> Until Friday Jul 16 you can buy any list below for just $150 each, 3 for $299 or 5 for $399: All lists are 100% optin and are 6 months or newer. == HEALTHCARE LISTS == * Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers * Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers * Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers * Dentists - 164k records, 45k emails, 77k fax numbers * Veterinarians - 78,986 total records with 1,438?emails and 1,050?fax numbers * Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) * National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics * Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) * Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees * Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers * Oncology Doctors - 2,200 records all with emails * US Surgery Centers - 85k records and 14k emails * Massage Therapists - 76,701 records and 8,305 emails * Acupuncturists - 23,988 records 1,826 emails * Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers * Mental Health Counselors - 283,184 records 7,206 emails * Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers * Optometrists - 63,837 records 2,015 emails * Psychologists - 272,188 records and 9,874 emails == BUSINESS AND FINANCE LISTS == * Hotels - 34,815 total records * 1,642 emails * Real Estate Agents - 1 million records with emails * American Business Email List - 2 million emails various businesses * US New Business Database - 4.8 million records all with emails * Manufacturers Database - 1,057,119 records with 476,509 emails * Financial Planners Database - 148,857 records all with emails * Finance and Money Professionals Database - 116,568 records all with emails == CONSUMER LISTS == * American Consumer Database - 300,000 records all with emails. * Credit Inquiries Database - 1 million Full Data Records all with emails * American Homeowners - 1 million Full Data Records all with emails == PROFESSIONALS LISTS == * USA Lawyers Database - 269,787 records with 235,244 emails * Police and Sheriff Services - 42,987 records and 114 emails * Criminal Attorneys - 142,906 total records, 99,857 emails email me if you're interested: accuratedata at gmx.com to adjust your subscription status email to offthelist at gmx.com From oleg at redhat.com Wed Jul 14 23:37:54 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Jul 2010 01:37:54 +0200 Subject: gdbstub initial code In-Reply-To: <20100713133550.GC31646@redhat.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> <20100713133550.GC31646@redhat.com> Message-ID: <20100714233754.GA26687@redhat.com> On 07/13, Oleg Nesterov wrote: > > And now I am going to rewrite this code without adding the new > functionality (this shouldn't take much time, hopefully today). Next iteration. Misc changes, but still in the initial stage. The only visible change is that cont/ctrl-c pretends to work. Note that currently I am not even trying to do something meaningful with utrace. My only goal for now is to implement the very basic things like attach/detach/stop/cont/exit correctly from the remote protocol pov. And I want to do this "rightly", then we will discuss utrace issues. Oleg. -------------- next part -------------- #include #include #include #include #include #include static int d_echo; module_param_named(echo, d_echo, bool, 0); #define PACKET_SIZE 1024 #define BUFFER_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void pb_start(struct pbuf *pb) { WARN_ON(pb->pkt); pb_putc(pb, '$'); pb->pkt = pb->cur; } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (d_echo) printk(KERN_INFO "<= %.*s\n", copy, pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // XXX: TODO: gdb is single-thread, no locking currently. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define T printk(KERN_INFO "TRACE: %s:%d\n", __FUNCTION__, __LINE__) enum { NO_STOP, STOP_REQ, STOP_ACK, }; struct ugdb_context { int c_stop; const char *fake_rc; struct pid *pid; struct utrace_engine *engine; struct ugdb *c_ugdb; struct list_head node; }; struct ugdb { char g_ibuf[PACKET_SIZE]; int g_ilen; struct pbuf g_pbuf; bool g_no_ack; int g_err; struct list_head g_attached; struct ugdb_context *g_current; wait_queue_head_t g_wait; }; // XXX: Of course, this all is racy ---------------------------------- static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_context *context = engine->data; if (context->c_stop == NO_STOP) return UTRACE_RESUME; context->c_stop = STOP_ACK; wake_up_all(&context->c_ugdb->g_wait); return UTRACE_STOP; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, }; static int ugdb_stop_one(struct ugdb_context *context, const char *fake_rc) { int err; context->c_stop = STOP_REQ; context->fake_rc = fake_rc; err = utrace_control_pid(context->pid, context->engine, UTRACE_INTERRUPT); if (err == -EINPROGRESS) err = 0; return err; } static int ugdb_cont_one(struct ugdb_context *context) { if (context->c_stop == NO_STOP) return -EALREADY; context->c_stop = NO_STOP; context->fake_rc = NULL; utrace_control_pid(context->pid, context->engine, UTRACE_RESUME); return 0; } static int ugdb_wait_for_rc(struct ugdb *ugdb) { DEFINE_WAIT(wait); struct ugdb_context *context; int ret; for (;;) { prepare_to_wait(&ugdb->g_wait, &wait, TASK_INTERRUPTIBLE); list_for_each_entry(context, &ugdb->g_attached, node) { if (context->c_stop == STOP_ACK) { pb_packs(&ugdb->g_pbuf, context->fake_rc); context->fake_rc = NULL; } } ret = 0; if (pb_size(&ugdb->g_pbuf)) break; ret = -EINTR; if (signal_pending(current)) break; schedule(); } finish_wait(&ugdb->g_wait, &wait); return ret; } static int xxx_prepare_examine(struct task_struct *task, struct ugdb_context *context, struct utrace_examiner *exam) { for (;;) { int err; if (fatal_signal_pending(current)) return -EINTR; if (context->c_stop == NO_STOP) { printk(KERN_INFO "XXX: unexpected NO_STOP\n"); return -EINVAL; } if (context->c_stop != STOP_ACK) { schedule_timeout_interruptible(1); continue; } err = utrace_prepare_examine(task, context->engine, exam); if (!err || err == -ESRCH) return err; schedule_timeout_interruptible(1); } } static void ugdb_c_all(struct ugdb *ugdb, const char *fake_rc) { struct ugdb_context *context; list_for_each_entry(context, &ugdb->g_attached, node) { if (fake_rc) ugdb_stop_one(context, fake_rc); else ugdb_cont_one(context); } } static char *handle_vattach(struct ugdb *ugdb, char *cmd) { // XXX: MULTIPID int nr = simple_strtoul(cmd, NULL, 16); struct pid *pid = find_get_pid(nr); struct ugdb_context *context; int err; if (!pid) goto err; context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto free_pid; context->pid = pid; context->c_ugdb = ugdb; context->engine = utrace_attach_pid(pid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, context); if (IS_ERR(context->engine)) goto free_ctx; err = utrace_set_events_pid(pid, context->engine, UTRACE_EVENT(QUIESCE)); err = ugdb_stop_one(context, "S05"); if (err) goto free_engine; list_add_tail(&context->node, &ugdb->g_attached); ugdb->g_current = context; return NULL; free_engine: utrace_control_pid(pid, context->engine, UTRACE_DETACH); utrace_engine_put(context->engine); free_ctx: kfree(context); free_pid: put_pid(pid); err: return "E01"; } static void ugdb_detach_one(struct ugdb *ugdb, struct ugdb_context *context) { int ret; if (ugdb->g_current == context) ugdb->g_current = NULL; ret = utrace_control_pid(context->pid, context->engine, UTRACE_DETACH); if (ret == -EINPROGRESS) utrace_barrier_pid(context->pid, context->engine); utrace_engine_put(context->engine); list_del(&context->node); put_pid(context->pid); kfree(context); } static void ugdb_detach_all(struct ugdb *ugdb) { struct ugdb_context *context, *tmp; list_for_each_entry_safe(context, tmp, &ugdb->g_attached, node) ugdb_detach_one(ugdb, context); } static struct ugdb_context *find_context(struct ugdb *ugdb, int nr) { struct ugdb_context *context; if (!nr) return ugdb->g_current; list_for_each_entry(context, &ugdb->g_attached, node) if (pid_vnr(context->pid) == nr) return context; return NULL; } static char *handle_hg(struct ugdb *ugdb, char *cmd) { // XXX: MULTIPID int nr = simple_strtoul(cmd, NULL, 16); if (!ugdb->g_current || pid_vnr(ugdb->g_current->pid) != nr) ugdb->g_current = find_context(ugdb, nr); if (ugdb->g_current) return "OK"; return "E01"; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_g(struct ugdb *ugdb) { struct ugdb_context *context = ugdb->g_current; const struct user_regset_view *view; const struct user_regset *rset; struct utrace_examiner exam; struct user_regs_struct *pregs; struct task_struct *task; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->g_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->g_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->g_pbuf.cur + BUFFER_SIZE); if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (utrace_finish_examine(task, context->engine, &exam)) goto err; pb_start(&ugdb->g_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->g_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->g_pbuf) < sizeof(*pregs)); pb_end(&ugdb->g_pbuf); return NULL; err: return "E01"; } // !!!!!!!! UNCOMMENT THIS TO COMPILE !!!!!!!!!!!!!!!!!!!!!! //#define access_process_vm(task, addr, buf, len, rw) -EFAULT static void apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; char *err = "E01"; pb_start(&ugdb->g_pbuf); mbuf = pb_alloc_bs(&ugdb->g_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto end; } size = access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto end; pb_putbs(&ugdb->g_pbuf, mbuf, size); err = ""; end: pb_puts(&ugdb->g_pbuf, err); pb_end(&ugdb->g_pbuf); } static char *handle_m(struct ugdb *ugdb, char *cmd) { struct ugdb_context *context = ugdb->g_current; struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; sscanf(cmd, "m%lx,%lx", &addr, &size); if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (utrace_finish_examine(task, context->engine, &exam)) ; return NULL; err: return "E01"; } static char *handle_d(struct ugdb *ugdb) { // XXX: MULTIPID if (!ugdb->g_current) { printk(KERN_INFO "XXX: NULL detach\n"); return "E01"; } ugdb_detach_one(ugdb, ugdb->g_current); return "OK"; } #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { char *rc = ""; switch (cmd[0]) { case '!': rc = "OK"; break; case '?': rc = "W00"; break; case 'g': rc = handle_g(ugdb); break; case 'm': rc = handle_m(ugdb, cmd); break; case 'D': rc = handle_d(ugdb); break; case 'c': ugdb_c_all(ugdb, NULL); rc = NULL; break; case 'q': if (EQ(cmd, "qSupported")) { pb_packf(&ugdb->g_pbuf, "PacketSize=%x;QStartNoAckMode+", PACKET_SIZE); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { if (ugdb->g_current) { // XXX: MULTIPID int nr = pid_vnr(ugdb->g_current->pid); pb_packf(&ugdb->g_pbuf, "m%x", nr); rc = NULL; } } else if (EQ(cmd, "qsThreadInfo")) { rc = "l"; } else if (EQ(cmd, "qC")) { if (ugdb->g_current) { // XXX: MULTIPID int nr = pid_vnr(ugdb->g_current->pid); pb_packf(&ugdb->g_pbuf, "m%x", nr); rc = NULL; } } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; default: if (EQ(cmd, "QStartNoAckMode")) { ugdb->g_no_ack = true; rc = "OK"; } else if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "Hg")) { rc = handle_hg(ugdb, cmd); } } if (rc) pb_packs(&ugdb->g_pbuf, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->g_ibuf; int todo = ugdb->g_ilen; if (d_echo) printk(KERN_INFO "=> %.*s\n", ugdb->g_ilen, ugdb->g_ibuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: // XXX: Ctrl-C sends chr = 3, not implemented. printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->g_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->g_err = -EPROTO; case '+': break; case '\3': ugdb_c_all(ugdb, "S02"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->g_no_ack) pb_putc(&ugdb->g_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->g_ilen = todo; if (todo && cmds > ugdb->g_ibuf) memcpy(ugdb->g_ibuf, cmds, todo); } static struct ugdb *ugdb_inifin(struct ugdb *ugdb) { int err = 0; if (ugdb) goto dtor; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; pb_init(&ugdb->g_pbuf); INIT_LIST_HEAD(&ugdb->g_attached); init_waitqueue_head(&ugdb->g_wait); return ugdb; dtor: kfree(ugdb); put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_inifin(NULL); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { struct ugdb *ugdb = file->private_data; ugdb_detach_all(ugdb); ugdb_inifin(ugdb); return 0; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (count > PACKET_SIZE - ugdb->g_ilen) { count = PACKET_SIZE - ugdb->g_ilen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->g_ilen); } if (copy_from_user(ugdb->g_ibuf + ugdb->g_ilen, ubuf, count)) return -EFAULT; ugdb->g_ilen += count; process_commands(ugdb); *ppos += count; return count; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (!pb_size(&ugdb->g_pbuf)) { int err = ugdb_wait_for_rc(ugdb); if (err) return err; } if (pb_size(&ugdb->g_pbuf) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(&ugdb->g_pbuf), count); } count = pb_copy_to_user(&ugdb->g_pbuf, ubuf, count); if (count > 0) *ppos += count; return count; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains. return 0; } static const struct file_operations ugdb_f_ops = { .write = ugdb_f_write, .read = ugdb_f_read, .open = ugdb_f_open, .release = ugdb_f_release, .unlocked_ioctl = ugdb_f_ioctl, }; #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From vsbn at ssfh.com Thu Jul 15 05:55:18 2010 From: vsbn at ssfh.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Thu, 15 Jul 2010 05:55:18 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVstNO8vMr119/P8rncwO0=?= Message-ID: <201007150554.o6F5sqFa003899@mx1.redhat.com> utrace-devel??????? ?????2010?7?26?27??? ?????2010?7?29?30??? ?????2010?8?26-27? ?? ?????2010?8?30-31? ?? ?????2010?9?27-28? ?? ?????1600?/??,????* ?????????????????? ????????????????????????????? ???????CEO/?????????/???????/???????????/???????? ???????????PMO???????????????????????? ?????020-80560638?020-85917945 ???????????????chinammc2010 at 126.com??? ---------------------------------------------------------------------------------- ????????????????????????????95%???????????????? ??????????????: ??????????????????????????????? ??????????????? ????????????????????????? ???????????????????????????? ????????????????? ????????????????????????????????? ????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ??????? ---------------------------------------------------------------------------------- ???? 1.??????????????????????????????????????? 2.???????????????????????? 3.??????????????????????? 4.????????????????????????????????????????? 5.???????????? 6.??????????????????????????????????????????????????? 7.?????????????????????? 8.???????????????????????????????????????? Action Plan? ???????????????????? ------------------------------------------------------------------------------------- ???? ???????0.5? 1)???????????? ????????????????????1.5? 1)?????????????????? 2)?????????????? 3)?????????????? ???????????????????? ???????10????? ???????????????????????? ????????? 4)?????????????????????????????????????????????????????????????????????????????? 5)???????????? 6)??????? 7)?????????????? ??????????????? ???????? ???????????? ???????????????? ?????????? ???????????? ?????????????? ?????????????? ??????????????????? ????????????? 8??????????????????????? 9???????? ????????????????3.5? 1)???????? 2)????? 3)????????? ???????? ???????????? ?????????????? ????????????? ????????????????????????? ????????????????????????????? 4)????????? ???????????????? ?????????????????????????? ?????????????????????? ????????????????????? ????????? ????????? ??????????????????? ??????????????????? ??????????????????????? ??????????????????????????????? ??????????????????????????????????????????? ???????????????????? 5)????????? ????????????????? ?????????????????????? ?????????????????????????????????? ?????????????????????????????????????? ??????????????? 6)????????? ???????????? ??????????? ???????????? ??????????????????? 7)????????? ??? ?????????????? ???????5??? ????????????????? ????????????????? ??????? ?????????????QA???? ?????????? ?????????? ?????????????????QA??????? ??????????????????????? ???????????????1.5? 1)????????????????????????? 2)????????????????????????????? 3)????????? 4)????????????? 5)??????? 6)????????????? 7)?????????????????????? 8)???????? 9)??????????? 10)?????????????? 11)??????????? 12)?????????? 13)????????????? 14)???????????????? 15)?????????????????????????????????????????? 16)????????? 17)???????????????????? 18)????????? 19)?????????????????????? ???????????????????????????1.0? 1)???????? 2)???????????? 3)????????????????????????? 4)????????????????? 5)???????????? 6)?????????SMART??????????????PBC?? 7)?????????????SMART 8)?????????SMART???????????SMART 9)???????PDCA?? 10)????????????????????????????????? 11)?????????? 12)??????????? 13)PERT??????GANNT 14)???????????PERT? 15)?????????????????????????????? 16)???????????? 17)????????? 18)???????????? 19)??????????????????? ?????????????????????????????2.0? 1)???????????? 2)??????????? 3)???????????? 4)???????????? 5)????????????????? 6)????????? 7)???????? 8)???????? 9)???????/???? 10)??????????? 11)????????????? 12)???????????? 13)????????????????????????? 14)????????????????????????????? 15)???????????????????????????????????????????????????????????????????????? 16)??????????????????????????????? 17)???? 30 ???????????????????????????????????????????????????????????? 18)?????????????????????????????????? 19)????????????????????????????????? 20)????????????????????????????? 21)??????????????????????? 22)??????????????????? ?? ?????????????????????????1.5? 1)??????????? 2)?????????????? 3)????????? 4)?????????????????????? 5)???????????????????????? 6)?????????????????????? 7)??????????????????????????? 8)???????????????????????? 9)?????????????????????????? 10)?????????????????????? 11)????????????????????????? 12)??????????????????????PCB? 13)????????????????? ???? ???????????????? ???????????????????????? ?????????????????? ?????????? ??????????????????????????????? 14)?????????????? 15)???????????? 16)??????????????????? 17)?????????? 18)??????????????????? 19)???????????????? 20)???????????? 21)??????????????????? 22)????????????????????????? 23)??????? ???????????????????????????2.0? 1)?????????? 2)???????????? 3)?????????????????????? 4)?????????????????? 5)???????? 6)???????????????? 7)???????????????? 8)???????????????????????? ????????? ????????????????????? ??????????KPI????????????? ?????????BSC?????????? ????????PBC????????????? ?????360????????????? ????? ???????????????? ??????????????????? ???????????????? 9)????????????????? ??????????????? ????????7??????????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????? ??????????????????????QA?????????????????? 10)???????????????????? ?????????? ???????????????????? ????????????????????? ?????????????????????? ?????????????????????????????????????????????? ?????????????????? ?????????????????? ?????????????????????? ??????????????????????????? ????????????????????????????????????????????? ??????????????? ?????????????????????????? 11)????? ???????????????????0.5? 1)????????? 2)??????? 3)????????????????? 4)??????????? ????????????????????? -------------------------------------------------------------------------------------------- ???? Giles ???? ?????10?????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ?????IPD??????ITS&P?????IPD????????????????????????? ???IPD????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????????????????????10????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????? ----------------------------------------------------------------------------------------- ??????????????????020-62351156? ???????? ??? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638??? From nbsg at qrwe.com Thu Jul 15 10:41:04 2010 From: nbsg at qrwe.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Thu, 15 Jul 2010 18:41:04 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0NDV/rmk1/fNs7PvudzA7Q==?= Message-ID: <201007151041.o6FAevxS031742@mx1.redhat.com> utrace-devel???????????????? ??????????2010??7??17-18?? ???? ??????????2010??7??23-24?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From drt at dftt.com Fri Jul 16 01:35:59 2010 From: drt at dftt.com (=?GB2312?B?x+vXqs/gudi4utTwyMs=?=) Date: Thu, 15 Jul 2010 21:35:59 -0400 Subject: =?GB2312?B?dXRyYWNlLWRldmVsQHJlZGhhdC5jb23Qwreoz8K1xMjLwabXytS0udzA7dbG?= Message-ID: <201007160135.o6G1Zvh4000854@mx1.redhat.com> =?GB2312?B?tsjJ6LzG?= To: utrace-devel at redhat.com Content-Type: text/plain;charset="GB2312" Date: Fri, 16 Jul 2010 09:36:03 +0800 X-Priority: 2 X-Mailer: Foxmail 4.2 [cn] ?????????????????????????????????????? ??????????2010??7??16-17?? ???? ??????????2010??7??23-24?? ???? ??????????2010??7??30-31?? ???? ??????????2200/???????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ----------------------------------------------------------------------------------- ????????????????????????????????????????????????????????????????????????????2008??1??1?????????? ??????????????????????????2008??5??1??????????, ?????????????????????????????????????????????? ???????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? --------------------------------------------------------------------------------------------- ???????? ?????????????????????? ?????????????????????????????? ?????? ?????????????? 1???????????????????????????? 2???????????????????????????? 3?????????????????????????????? ?????? ?????????? 1.????????????????????????????????????; 2.????????????????????????????????????????????????????; ?????? ?????????????????????????????????? 1??????????????????????????????????????????????????; 2?????????????????????? ?????? ?????????????????????????????? 1???????????????? 2?????????????????????????????? 3?????????????????????????????????????? 4?????????????????????????????? 5?????????????????????????????????????????? ???????????????????????????? 1?????????????????????????????????????????? 2???????????????????????? 3?????????????????????????????????????? 4???????????????????????????????????? 5?????????????????????????????????????????????????????????????????????????????? 6?????????????????????????????? 7?????????????????????????? 8?????????????????????????????????????? 9?????????????????????????? 10???????????????????????????????????????????????????????????????????????? ?????????????????????????????????????? 1??????????????????????????????????????????????????9?????? 2??????????????????????????????????????????????????????????12?????? 3?????????????????????????????? 4?????????????????????????????? ???????????????????????????? 1???????????????? 2?????????????? 3?????????????? 4???????????????????? 5???????????????? 6?????????????????????????????? ?????????????????????????? ?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????? ???????????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????? ???????????????????? ?????????????????????????????????????????????? ???????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????? ?????????????????????? ???????????????????????????? ???????????????????????????????? ???????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????? ?????????????????????????? ???????????????????????? ?????????????????????????????? ?????????????????????? ?????????????????????? ?????????????????????????? ???????????????????? ?????????????????????????????? ?????????????????????????? ?????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????? ???????????????????? 1.???????????? 2.???????????? 3?????????????????????? 4?????????????????????? 5???????????????????????????? 6?????????????????? 7?????????????????? 8?????????????? ?????????????????????????? a)?????????????????? b)?????????????? c)?????????????????? d)?????????????????? --------------------------------------------------------------- ???????????????????????????????????????????????????? ?? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? 2007????????????????????????????????????????????????????????95%?????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????07?????????????????? ????300????????????????1500?? ??????????????????95%????????????????????????1300???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????1000?????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? ????????????????????????????????????????????????SONY????????????????????????????PHILIP?????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????? HP???????????????????????????????????? =============================================================================== ????????????????????????????????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ???????????????? ?????? ?????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From roland at redhat.com Fri Jul 16 07:47:46 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 16 Jul 2010 00:47:46 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Oleg Nesterov's message of Thursday, 15 July 2010 01:37:54 +0200 <20100714233754.GA26687@redhat.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> <20100713133550.GC31646@redhat.com> <20100714233754.GA26687@redhat.com> Message-ID: <20100716074746.C063C4C853@magilla.sf.frob.com> > Note that currently I am not even trying to do something meaningful > with utrace. My only goal for now is to implement the very basic things > like attach/detach/stop/cont/exit correctly from the remote protocol > pov. And I want to do this "rightly", then we will discuss utrace > issues. Ok. I think you might need select to work on the pseudofile for gdb to be happy. I'm not sure on the situation about that. Thanks, Roland From lekindqiq0337 at 21cn.com Fri Jul 16 11:17:38 2010 From: lekindqiq0337 at 21cn.com (lekindqiq0337 at 21cn.com) Date: Fri, 16 Jul 2010 19:17:38 +0800 (CST) Subject: =?UTF-8?B?5pyJLOWPkeWugOelqC/ku6PlvIDikojikoo=?= =?UTF-8?B?4pKM5Lqg4pKK4pKK4pKL5a6A4pKN4pKK4pKO4pKN4pKM?= Message-ID: <24787734.269311279279058691.JavaMail.root@webmail1> An HTML attachment was scrubbed... URL: From haggled at westcapemay.us Fri Jul 16 11:32:53 2010 From: haggled at westcapemay.us (Meineke Purvines) Date: Fri, 16 Jul 2010 13:32:53 +0200 Subject: talk to him a little, and lau Message-ID: <4685d41f20100716112927@westcapemay.us> A non-text attachment was scrubbed... Name: coups.png Type: image/png Size: 22816 bytes Desc: not available URL: From oleg at redhat.com Fri Jul 16 15:11:28 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Jul 2010 17:11:28 +0200 Subject: gdbstub initial code In-Reply-To: <20100716074746.C063C4C853@magilla.sf.frob.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> <20100713133550.GC31646@redhat.com> <20100714233754.GA26687@redhat.com> <20100716074746.C063C4C853@magilla.sf.frob.com> Message-ID: <20100716151128.GA8876@redhat.com> On 07/16, Roland McGrath wrote: > > > Note that currently I am not even trying to do something meaningful > > with utrace. My only goal for now is to implement the very basic things > > like attach/detach/stop/cont/exit correctly from the remote protocol > > pov. And I want to do this "rightly", then we will discuss utrace > > issues. > > Ok. I think you might need select to work on the pseudofile for gdb to be > happy. I'm not sure on the situation about that. Ah, it is easy to implement ugdb_f_ops->poll(). I think. The only problem is that gdb doesn't try to use select. Perhaps it sees S_IFREG, I didn't check. But, it turns out, the multithreading is not trivial, and nasty. Because, unless I missed something a) remote protocol is very stupid, and b) gdb is buggy. I was going to add the threading support today, but I guess I have to really ask the questions before I can do this. So I am attaching the yesterday's version. Changes: - cleanups/fixes to make cont/^C really work - handle tracee's exit Oleg. -------------- next part -------------- #include #include #include #include #include #include static int d_echo; module_param_named(echo, d_echo, bool, 0); #define PACKET_SIZE 1024 #define BUFFER_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void pb_start(struct pbuf *pb) { WARN_ON(pb->pkt); pb_putc(pb, '$'); pb->pkt = pb->cur; } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (d_echo) printk(KERN_INFO "<= %.*s\n", copy, pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // XXX: TODO: gdb is single-thread, no locking currently. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define T printk(KERN_INFO "TRACE: %s:%d\n", __FUNCTION__, __LINE__) enum { STOP_RUN, STOP_REQ, STOP_ACK, STOP_FIN, }; struct ugdb_context { int c_stop; int c_exit; const char *fake_rc; struct pid *pid; struct utrace_engine *engine; struct ugdb *c_ugdb; struct list_head node; }; struct ugdb { char g_ibuf[PACKET_SIZE]; int g_ilen; struct pbuf g_pbuf; bool g_no_ack; int g_err; struct list_head g_attached; struct ugdb_context *g_current; wait_queue_head_t g_wait; }; // XXX: Of course, this all is racy ---------------------------------- static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_context *context = engine->data; if (event == UTRACE_EVENT(DEATH)) { context->c_exit = current->exit_code | INT_MIN; goto ack; } if (context->c_stop == STOP_RUN) return UTRACE_RESUME; if (context->c_stop != STOP_REQ) printk(KERN_INFO "XXX: %d, report_quiesce bad c_stop: %d\n", pid_vnr(context->pid), context->c_stop); ack: context->c_stop = STOP_ACK; wake_up_all(&context->c_ugdb->g_wait); return UTRACE_STOP; } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { return UTRACE_RESUME; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_death = ugdb_report_death, }; static int ugdb_stop_one(struct ugdb_context *context, const char *fake_rc) { int err; if (context->c_stop != STOP_RUN) return 0; context->c_stop = STOP_REQ; context->fake_rc = fake_rc; err = utrace_control_pid(context->pid, context->engine, UTRACE_INTERRUPT); if (err == -EINPROGRESS) err = 0; return err; } static int ugdb_cont_one(struct ugdb_context *context) { if (context->c_stop == STOP_RUN) return -EALREADY; context->c_stop = STOP_RUN; context->fake_rc = NULL; utrace_control_pid(context->pid, context->engine, UTRACE_RESUME); return 0; } static int ugdb_wait_for_rc(struct ugdb *ugdb) { DEFINE_WAIT(wait); struct ugdb_context *context; int ret; for (;;) { prepare_to_wait(&ugdb->g_wait, &wait, TASK_INTERRUPTIBLE); list_for_each_entry(context, &ugdb->g_attached, node) { if (context->c_stop == STOP_ACK) { context->c_stop = STOP_FIN; if (context->c_exit) { int c = context->c_exit & 0xff; char r = 'X'; if (!c) { c = (context->c_exit & 0xff) << 8; r = 'W'; } pb_packf(&ugdb->g_pbuf, "%c%02x", r, c); continue; } if (!context->fake_rc) { printk(KERN_INFO "XXX: %d NULL rc\n", pid_vnr(context->pid)); continue; } pb_packs(&ugdb->g_pbuf, context->fake_rc); } } ret = 0; if (pb_size(&ugdb->g_pbuf)) break; ret = -EINTR; if (signal_pending(current)) break; schedule(); } finish_wait(&ugdb->g_wait, &wait); return ret; } static int xxx_prepare_examine(struct task_struct *task, struct ugdb_context *context, struct utrace_examiner *exam) { for (;;) { if (fatal_signal_pending(current)) return -EINTR; if (context->c_stop == STOP_RUN) { printk(KERN_INFO "XXX: %d unexpected STOP_RUN\n", pid_vnr(context->pid)); return -EINVAL; } if (context->c_stop != STOP_REQ) { int err = utrace_prepare_examine(task, context->engine, exam); if (!err || err == -ESRCH) return err; } schedule_timeout_interruptible(1); } } static void ugdb_c_all(struct ugdb *ugdb, const char *fake_rc) { struct ugdb_context *context; list_for_each_entry(context, &ugdb->g_attached, node) { if (fake_rc) ugdb_stop_one(context, fake_rc); else ugdb_cont_one(context); } } static char *handle_vattach(struct ugdb *ugdb, char *cmd) { // XXX: MULTIPID int nr = simple_strtoul(cmd, NULL, 16); struct pid *pid = find_get_pid(nr); struct ugdb_context *context; int err; if (!pid) goto err; context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto free_pid; context->pid = pid; context->c_ugdb = ugdb; context->engine = utrace_attach_pid(pid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, context); if (IS_ERR(context->engine)) goto free_ctx; err = utrace_set_events_pid(pid, context->engine, UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(DEATH)); err = ugdb_stop_one(context, "S05"); if (err) goto free_engine; list_add_tail(&context->node, &ugdb->g_attached); ugdb->g_current = context; return NULL; free_engine: utrace_control_pid(pid, context->engine, UTRACE_DETACH); utrace_engine_put(context->engine); free_ctx: kfree(context); free_pid: put_pid(pid); err: return "E01"; } static void ugdb_detach_one(struct ugdb *ugdb, struct ugdb_context *context) { int ret; if (ugdb->g_current == context) ugdb->g_current = NULL; ret = utrace_control_pid(context->pid, context->engine, UTRACE_DETACH); if (ret == -EINPROGRESS) utrace_barrier_pid(context->pid, context->engine); utrace_engine_put(context->engine); list_del(&context->node); put_pid(context->pid); kfree(context); } static void ugdb_detach_all(struct ugdb *ugdb) { struct ugdb_context *context, *tmp; list_for_each_entry_safe(context, tmp, &ugdb->g_attached, node) ugdb_detach_one(ugdb, context); } static struct ugdb_context *find_context(struct ugdb *ugdb, int nr) { struct ugdb_context *context; if (!nr) return ugdb->g_current; list_for_each_entry(context, &ugdb->g_attached, node) if (pid_vnr(context->pid) == nr) return context; return NULL; } static char *handle_hg(struct ugdb *ugdb, char *cmd) { // XXX: MULTIPID int nr = simple_strtoul(cmd, NULL, 16); if (!ugdb->g_current || pid_vnr(ugdb->g_current->pid) != nr) ugdb->g_current = find_context(ugdb, nr); if (ugdb->g_current) return "OK"; return "E01"; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_g(struct ugdb *ugdb) { struct ugdb_context *context = ugdb->g_current; const struct user_regset_view *view; const struct user_regset *rset; struct utrace_examiner exam; struct user_regs_struct *pregs; struct task_struct *task; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->g_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->g_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->g_pbuf.cur + BUFFER_SIZE); if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (utrace_finish_examine(task, context->engine, &exam)) goto err; pb_start(&ugdb->g_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->g_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->g_pbuf) < sizeof(*pregs)); pb_end(&ugdb->g_pbuf); return NULL; err: return "E01"; } // !!!!!!!! UNCOMMENT THIS TO COMPILE !!!!!!!!!!!!!!!!!!!!!! //#define access_process_vm(task, addr, buf, len, rw) -EFAULT static void apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; char *err = "E01"; pb_start(&ugdb->g_pbuf); mbuf = pb_alloc_bs(&ugdb->g_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto end; } size = access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto end; pb_putbs(&ugdb->g_pbuf, mbuf, size); err = ""; end: pb_puts(&ugdb->g_pbuf, err); pb_end(&ugdb->g_pbuf); } static char *handle_m(struct ugdb *ugdb, char *cmd) { struct ugdb_context *context = ugdb->g_current; struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; sscanf(cmd, "m%lx,%lx", &addr, &size); if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (utrace_finish_examine(task, context->engine, &exam)) ; return NULL; err: return "E01"; } static char *handle_d(struct ugdb *ugdb) { // XXX: MULTIPID if (!ugdb->g_current) { printk(KERN_INFO "XXX: NULL detach\n"); return "E01"; } ugdb_detach_one(ugdb, ugdb->g_current); return "OK"; } #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { char *rc = ""; switch (cmd[0]) { case '!': rc = "OK"; break; case '?': rc = "W00"; break; case 'g': rc = handle_g(ugdb); break; case 'm': rc = handle_m(ugdb, cmd); break; case 'D': rc = handle_d(ugdb); break; case 'c': ugdb_c_all(ugdb, NULL); rc = NULL; break; case 'q': if (EQ(cmd, "qSupported")) { pb_packf(&ugdb->g_pbuf, "PacketSize=%x;QStartNoAckMode+", PACKET_SIZE); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { if (ugdb->g_current) { // XXX: MULTIPID int nr = pid_vnr(ugdb->g_current->pid); pb_packf(&ugdb->g_pbuf, "m%x", nr); rc = NULL; } } else if (EQ(cmd, "qsThreadInfo")) { rc = "l"; } else if (EQ(cmd, "qC")) { if (ugdb->g_current) { // XXX: MULTIPID int nr = pid_vnr(ugdb->g_current->pid); pb_packf(&ugdb->g_pbuf, "m%x", nr); rc = NULL; } } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; default: if (EQ(cmd, "QStartNoAckMode")) { ugdb->g_no_ack = true; rc = "OK"; } else if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "Hg")) { rc = handle_hg(ugdb, cmd); } } if (rc) pb_packs(&ugdb->g_pbuf, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->g_ibuf; int todo = ugdb->g_ilen; if (d_echo) printk(KERN_INFO "=> %.*s\n", ugdb->g_ilen, ugdb->g_ibuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: // XXX: Ctrl-C sends chr = 3, not implemented. printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->g_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->g_err = -EPROTO; case '+': break; case 0x3: ugdb_c_all(ugdb, "S02"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->g_no_ack) pb_putc(&ugdb->g_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->g_ilen = todo; if (todo && cmds > ugdb->g_ibuf) memcpy(ugdb->g_ibuf, cmds, todo); } static struct ugdb *ugdb_inifin(struct ugdb *ugdb) { int err = 0; if (ugdb) goto dtor; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; pb_init(&ugdb->g_pbuf); INIT_LIST_HEAD(&ugdb->g_attached); init_waitqueue_head(&ugdb->g_wait); return ugdb; dtor: kfree(ugdb); put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_inifin(NULL); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { struct ugdb *ugdb = file->private_data; ugdb_detach_all(ugdb); ugdb_inifin(ugdb); return 0; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (count > PACKET_SIZE - ugdb->g_ilen) { count = PACKET_SIZE - ugdb->g_ilen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->g_ilen); } if (copy_from_user(ugdb->g_ibuf + ugdb->g_ilen, ubuf, count)) return -EFAULT; ugdb->g_ilen += count; process_commands(ugdb); *ppos += count; return count; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (!pb_size(&ugdb->g_pbuf)) { int err = ugdb_wait_for_rc(ugdb); if (err) return err; } if (pb_size(&ugdb->g_pbuf) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(&ugdb->g_pbuf), count); } count = pb_copy_to_user(&ugdb->g_pbuf, ubuf, count); if (count > 0) *ppos += count; return count; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains. return 0; } static const struct file_operations ugdb_f_ops = { .write = ugdb_f_write, .read = ugdb_f_read, .open = ugdb_f_open, .release = ugdb_f_release, .unlocked_ioctl = ugdb_f_ioctl, }; #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From confirm-s2-a5bdxpdjp4nszc54h4eqqwjfpv0tvhcs-utrace-devel=redhat.com at yahoogrupos.com.br Sat Jul 17 02:17:14 2010 From: confirm-s2-a5bdxpdjp4nszc54h4eqqwjfpv0tvhcs-utrace-devel=redhat.com at yahoogrupos.com.br (Yahoo! Grupos) Date: 17 Jul 2010 02:17:14 -0000 Subject: Confirma=?ISO-8859-1?Q?=E7=E3?=o de pedido para entrar no grupo de_amigo_para_amigo Message-ID: <1279333034.31.64436.w4@yahoogrupos.com.br> Ol? utrace-devel at redhat.com, Recebemos sua solicita??o para entrar no grupo de_amigo_para_amigo do Yahoo! Grupos, um servi?o de comunidades online gratuito e super f?cil de usar. Este pedido expirar? em 7 dias. PARA ENTRAR NESTE GRUPO: 1) V? para o site do Yahoo! Grupos clicando neste link: http://br.groups.yahoo.com/i?i=a5bdxpdjp4nszc54h4eqqwjfpv0tvhcs&e=utrace-devel%40redhat%2Ecom (Se n?o funcionar, use os comandos para cortar e colar o link acima na barra de endere?o do seu navegador.) -OU- 2) RESPONDA a este e-mail clicando em "Responder" e depois em "Enviar", no seu programa de e-mail. Se voc? n?o fez esta solicita??o ou se n?o tem interesse em entrar no grupo de_amigo_para_amigo, por favor, ignore esta mensagem. Sauda??es, Atendimento ao usu?rio do Yahoo! Grupos O uso que voc? faz do Yahoo! Grupos est? sujeito aos http://br.yahoo.com/info/utos.html From maillist at discount.net Sat Jul 17 06:42:04 2010 From: maillist at discount.net (discount) Date: Sat, 17 Jul 2010 02:42:04 -0400 Subject: Best Discounts Message-ID: Online shopping for brand names at discounted prices http://www.fineandchic.com/?wm=14793&tr=8038 -------------- next part -------------- An HTML attachment was scrubbed... URL: From koe at iwqe.com Sat Jul 17 18:03:41 2010 From: koe at iwqe.com (=?GB2312?B?xeDRtQ==?=) Date: Sun, 18 Jul 2010 02:03:41 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0NDV/rmk1/fNs7PvudzA7Q==?= Message-ID: <201007171803.o6HI3S7B022264@mx1.redhat.com> utrace-devel???????????????? ??????????2010??7??23-24?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From diapausing at sn-info.co.uk Sun Jul 18 00:16:00 2010 From: diapausing at sn-info.co.uk (Picarello Wojtanowski) Date: Sun, 18 Jul 2010 02:16:00 +0200 Subject: . Mechanically he rep Message-ID: <4C42472B$426636@sn-info.co.uk> A non-text attachment was scrubbed... Name: mariachi.png Type: image/png Size: 23697 bytes Desc: not available URL: From liuxing1010 at 21cn.net Mon Jul 19 05:39:07 2010 From: liuxing1010 at 21cn.net (liuxing1010 at 21cn.net) Date: Mon, 19 Jul 2010 13:39:07 +0800 (CST) Subject: =?UTF-8?B?5bi46KeB5aSW5Lqk55eF5oCB55Sf55CGIA==?= Message-ID: <22447759.35721279517947617.JavaMail.root@pay1> An HTML attachment was scrubbed... URL: From confirm-s2-sejwlt0wbp0vfryo2wk42qsae1wbnbho-utrace-devel=redhat.com at yahoogrupos.com.br Mon Jul 19 13:11:36 2010 From: confirm-s2-sejwlt0wbp0vfryo2wk42qsae1wbnbho-utrace-devel=redhat.com at yahoogrupos.com.br (Yahoo! Grupos) Date: 19 Jul 2010 13:11:36 -0000 Subject: Confirma=?ISO-8859-1?Q?=E7=E3?=o de pedido para entrar no grupo de_amigo_para_amigo Message-ID: <1279545096.35.53047.w7@yahoogrupos.com.br> Ol? utrace-devel at redhat.com, Recebemos sua solicita??o para entrar no grupo de_amigo_para_amigo do Yahoo! Grupos, um servi?o de comunidades online gratuito e super f?cil de usar. Este pedido expirar? em 7 dias. PARA ENTRAR NESTE GRUPO: 1) V? para o site do Yahoo! Grupos clicando neste link: http://br.groups.yahoo.com/i?i=sejwlt0wbp0vfryo2wk42qsae1wbnbho&e=utrace-devel%40redhat%2Ecom (Se n?o funcionar, use os comandos para cortar e colar o link acima na barra de endere?o do seu navegador.) -OU- 2) RESPONDA a este e-mail clicando em "Responder" e depois em "Enviar", no seu programa de e-mail. Se voc? n?o fez esta solicita??o ou se n?o tem interesse em entrar no grupo de_amigo_para_amigo, por favor, ignore esta mensagem. Sauda??es, Atendimento ao usu?rio do Yahoo! Grupos O uso que voc? faz do Yahoo! Grupos est? sujeito aos http://br.yahoo.com/info/utos.html From banishment at mallinson.ca Mon Jul 19 15:50:53 2010 From: banishment at mallinson.ca (Subler Levene) Date: Mon, 19 Jul 2010 17:50:53 +0200 Subject: the fishes al Message-ID: <297A57A4447CBFE822C32A1162DD@mallinson.ca> A non-text attachment was scrubbed... Name: epilepsy.png Type: image/png Size: 19448 bytes Desc: not available URL: From drjohnfranks at gmail.com Wed Jul 14 16:02:54 2010 From: drjohnfranks at gmail.com (Reed Rogers) Date: Wed, 14 Jul 2010 10:02:54 -0600 (CST) Subject: Business/Medical/Consumer Mailing lists Message-ID: <20100714160254.9F04E8572FB@elastix.example.com> Until Friday Jul 16 you can buy any list below for just $150 each, 3 for $299 or 5 for $399: All lists are 100% optin and are 6 months or newer. == HEALTHCARE LISTS == * Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers * Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers * Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers * Dentists - 164k records, 45k emails, 77k fax numbers * Veterinarians - 78,986 total records with 1,438?emails and 1,050?fax numbers * Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) * National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics * Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) * Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees * Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers * Oncology Doctors - 2,200 records all with emails * US Surgery Centers - 85k records and 14k emails * Massage Therapists - 76,701 records and 8,305 emails * Acupuncturists - 23,988 records 1,826 emails * Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers * Mental Health Counselors - 283,184 records 7,206 emails * Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers * Optometrists - 63,837 records 2,015 emails * Psychologists - 272,188 records and 9,874 emails == BUSINESS AND FINANCE LISTS == * Hotels - 34,815 total records * 1,642 emails * Real Estate Agents - 1 million records with emails * American Business Email List - 2 million emails various businesses * US New Business Database - 4.8 million records all with emails * Manufacturers Database - 1,057,119 records with 476,509 emails * Financial Planners Database - 148,857 records all with emails * Finance and Money Professionals Database - 116,568 records all with emails == CONSUMER LISTS == * American Consumer Database - 300,000 records all with emails. * Credit Inquiries Database - 1 million Full Data Records all with emails * American Homeowners - 1 million Full Data Records all with emails == PROFESSIONALS LISTS == * USA Lawyers Database - 269,787 records with 235,244 emails * Police and Sheriff Services - 42,987 records and 114 emails * Criminal Attorneys - 142,906 total records, 99,857 emails email me if you're interested: accuratedata at gmx.com By emailing offthelist at gmx.com you will have your email taken off From oleg at redhat.com Mon Jul 19 16:25:25 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 19 Jul 2010 18:25:25 +0200 Subject: gdbstub initial code In-Reply-To: <20100716151128.GA8876@redhat.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> <20100713133550.GC31646@redhat.com> <20100714233754.GA26687@redhat.com> <20100716074746.C063C4C853@magilla.sf.frob.com> <20100716151128.GA8876@redhat.com> Message-ID: <20100719162525.GA22027@redhat.com> Changes: - make it work without exporting access_process_vm(). Suprisingly, kallsyms.c has useful exports. - Add multiprocess mode. Incomplete, in particular parse_pids() can't parse the negative hex pids. At first I tried to support both multiprocess and !multiprocess modes, but this needs too many "unnecessary" code which I'd like to avoid, at least now. So this version requires "multiprocess+" in qSupported, otherwise "target extended-remote" fails. Please let me know if we need both modes. Oleg. -------------- next part -------------- #include #include #include #include #include #include static int d_echo; module_param_named(echo, d_echo, bool, 0); #define PACKET_SIZE 1024 #define BUFFER_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void pb_start(struct pbuf *pb) { WARN_ON(pb->pkt); pb_putc(pb, '$'); pb->pkt = pb->cur; } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (d_echo) printk(KERN_INFO "<= %.*s\n", copy, pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // XXX: TODO: gdb is single-thread, no locking currently. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define T printk(KERN_INFO "TRACE: %s:%d\n", __FUNCTION__, __LINE__) enum { STOP_RUN, STOP_REQ, STOP_ACK, STOP_FIN, }; struct ugdb_context { int c_stop; int c_exit; const char *fake_rc; int c_pid, c_tid; char c_xid[32]; struct pid *pid; struct utrace_engine *engine; struct ugdb *c_ugdb; struct list_head node; }; struct ugdb { char g_ibuf[PACKET_SIZE]; int g_ilen; struct pbuf g_pbuf; bool g_no_ack; int g_err; struct list_head g_attached; struct ugdb_context *g_current; wait_queue_head_t g_wait; }; // XXX: Of course, this all is racy ---------------------------------- static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_context *context = engine->data; if (event == UTRACE_EVENT(DEATH)) { context->c_exit = current->exit_code | INT_MIN; goto ack; } if (context->c_stop == STOP_RUN) return UTRACE_RESUME; if (context->c_stop != STOP_REQ) printk(KERN_INFO "XXX: %d, report_quiesce bad c_stop: %d\n", context->c_tid, context->c_stop); ack: context->c_stop = STOP_ACK; wake_up_all(&context->c_ugdb->g_wait); return UTRACE_STOP; } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { return UTRACE_RESUME; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_death = ugdb_report_death, }; static int ugdb_stop_one(struct ugdb_context *context, const char *fake_rc) { int err; if (context->c_stop != STOP_RUN) return 0; context->c_stop = STOP_REQ; context->fake_rc = fake_rc; err = utrace_control_pid(context->pid, context->engine, UTRACE_INTERRUPT); if (err == -EINPROGRESS) err = 0; return err; } static int ugdb_cont_one(struct ugdb_context *context) { if (context->c_stop == STOP_RUN) return -EALREADY; context->c_stop = STOP_RUN; context->fake_rc = NULL; utrace_control_pid(context->pid, context->engine, UTRACE_RESUME); return 0; } static int ugdb_wait_for_rc(struct ugdb *ugdb) { DEFINE_WAIT(wait); struct ugdb_context *context; int ret; for (;;) { prepare_to_wait(&ugdb->g_wait, &wait, TASK_INTERRUPTIBLE); list_for_each_entry(context, &ugdb->g_attached, node) { if (context->c_stop == STOP_ACK) { context->c_stop = STOP_FIN; if (context->c_exit) { int c = context->c_exit & 0xff; char r = 'X'; if (!c) { c = (context->c_exit & 0xff) << 8; r = 'W'; } pb_packf(&ugdb->g_pbuf, "%c%02x", r, c); continue; } if (!context->fake_rc) { printk(KERN_INFO "XXX: %d NULL rc\n", context->c_tid); continue; } pb_packs(&ugdb->g_pbuf, context->fake_rc); } } ret = 0; if (pb_size(&ugdb->g_pbuf)) break; ret = -EINTR; if (signal_pending(current)) break; schedule(); } finish_wait(&ugdb->g_wait, &wait); return ret; } static int xxx_prepare_examine(struct task_struct *task, struct ugdb_context *context, struct utrace_examiner *exam) { for (;;) { if (fatal_signal_pending(current)) return -EINTR; if (context->c_stop == STOP_RUN) { printk(KERN_INFO "XXX: %d unexpected STOP_RUN\n", context->c_tid); return -EINVAL; } if (context->c_stop != STOP_REQ) { int err = utrace_prepare_examine(task, context->engine, exam); if (!err || err == -ESRCH) return err; } schedule_timeout_interruptible(1); } } static void ugdb_c_all(struct ugdb *ugdb, const char *fake_rc) { struct ugdb_context *context; list_for_each_entry(context, &ugdb->g_attached, node) { if (fake_rc) ugdb_stop_one(context, fake_rc); else ugdb_cont_one(context); } } static char *handle_vattach(struct ugdb *ugdb, char *cmd) { int nr = simple_strtoul(cmd, NULL, 16); struct pid *pid = find_get_pid(nr); struct ugdb_context *context; int err; if (!pid) goto err; context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto free_pid; context->c_pid = nr; context->c_tid = nr; snprintf(context->c_xid, sizeof(context->c_xid), "p%x.%x", context->c_pid, context->c_tid); context->pid = pid; context->c_ugdb = ugdb; context->engine = utrace_attach_pid(pid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, context); if (IS_ERR(context->engine)) goto free_ctx; err = utrace_set_events_pid(pid, context->engine, UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(DEATH)); err = ugdb_stop_one(context, "S05"); if (err) goto free_engine; list_add_tail(&context->node, &ugdb->g_attached); ugdb->g_current = context; return NULL; free_engine: utrace_control_pid(pid, context->engine, UTRACE_DETACH); utrace_engine_put(context->engine); free_ctx: kfree(context); free_pid: put_pid(pid); err: return "E01"; } static void ugdb_detach_one(struct ugdb *ugdb, struct ugdb_context *context) { int ret; if (ugdb->g_current == context) ugdb->g_current = NULL; ret = utrace_control_pid(context->pid, context->engine, UTRACE_DETACH); if (ret == -EINPROGRESS) utrace_barrier_pid(context->pid, context->engine); utrace_engine_put(context->engine); list_del(&context->node); put_pid(context->pid); kfree(context); } static bool context_pids(struct ugdb_context *context, int pid, int tid) { if (pid > 0 && context->c_pid != pid) return false; if (tid > 0 && context->c_tid != tid) return false; return true; } static void ugdb_detach_many(struct ugdb *ugdb, int pid, int tid) { struct ugdb_context *context, *tmp; list_for_each_entry_safe(context, tmp, &ugdb->g_attached, node) if (context_pids(context, pid, tid)) ugdb_detach_one(ugdb, context); } static struct ugdb_context *find_context(struct ugdb *ugdb, int pid, int tid) { struct ugdb_context *context; list_for_each_entry(context, &ugdb->g_attached, node) if (context_pids(context, pid, tid)) return context; return NULL; } static bool parse_pids(char *cmd, int *ppid, int *ptid) { int r = sscanf(cmd, "p%x.%x", ppid, ptid); if (r == 2) return true; WARN("ERR!! parse_pids(%s) failed\n", cmd); return false; } static char *handle_hg(struct ugdb *ugdb, char *cmd) { int pid, tid; if (parse_pids(cmd, &pid, &tid)) { ugdb->g_current = find_context(ugdb, pid, tid); if (ugdb->g_current) return "OK"; } return "E01"; } static const char *handle_t(struct ugdb *ugdb, char *cmd) { int pid, tid; if (!parse_pids(cmd, &pid, &tid)) goto err; if (pid <= 0 || tid <= 0) printk(KERN_INFO "XXX: T with multipid? %s\n", cmd); if (find_context(ugdb, pid, tid)) return "OK"; err: return "E01"; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_g(struct ugdb *ugdb) { struct ugdb_context *context = ugdb->g_current; const struct user_regset_view *view; const struct user_regset *rset; struct utrace_examiner exam; struct user_regs_struct *pregs; struct task_struct *task; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (!context) goto err; if (pb_room(&ugdb->g_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->g_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->g_pbuf.cur + BUFFER_SIZE); task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (utrace_finish_examine(task, context->engine, &exam)) goto err; pb_start(&ugdb->g_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->g_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->g_pbuf) < sizeof(*pregs)); pb_end(&ugdb->g_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static void apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; char *err = "E01"; pb_start(&ugdb->g_pbuf); mbuf = pb_alloc_bs(&ugdb->g_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto end; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto end; pb_putbs(&ugdb->g_pbuf, mbuf, size); err = ""; end: pb_puts(&ugdb->g_pbuf, err); pb_end(&ugdb->g_pbuf); } static const char *handle_m(struct ugdb *ugdb, char *cmd) { struct ugdb_context *context = ugdb->g_current; struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; if (!context) goto err; task = pid_task(context->pid, PIDTYPE_PID); if (!task) goto err; if (xxx_prepare_examine(task, context, &exam)) goto err; apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (utrace_finish_examine(task, context->engine, &exam)) ; return NULL; err: return "E01"; } static const char *handle_d(struct ugdb *ugdb, char *cmd) { int nr = simple_strtol(cmd, NULL, 16); ugdb_detach_many(ugdb, nr, -1); return "OK"; } #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { const char *rc = ""; switch (cmd[0]) { case '!': rc = "OK"; break; case '?': rc = "W00"; break; case 'g': rc = handle_g(ugdb); break; case 'm': rc = handle_m(ugdb, cmd); break; case 'c': ugdb_c_all(ugdb, NULL); rc = NULL; break; case 'T': rc = handle_t(ugdb, cmd + 1); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't works without multiprocess\n"); ugdb->g_err = -EPROTONOSUPPORT; break; } pb_packf(&ugdb->g_pbuf, "PacketSize=%x;QStartNoAckMode+;multiprocess+", PACKET_SIZE); rc = NULL; } else if (EQ(cmd, "qC")) { if (ugdb->g_current) { pb_packf(&ugdb->g_pbuf, "QC%s", ugdb->g_current->c_xid); rc = NULL; } } else if (EQ(cmd, "qfThreadInfo")) { if (ugdb->g_current) { pb_packf(&ugdb->g_pbuf, "m%s", ugdb->g_current->c_xid); rc = NULL; } } else if (EQ(cmd, "qsThreadInfo")) { rc = "l"; } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; default: if (EQ(cmd, "QStartNoAckMode")) { ugdb->g_no_ack = true; rc = "OK"; } else if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "D;")) { rc = handle_d(ugdb, cmd); } else if (EQ(cmd, "Hg")) { rc = handle_hg(ugdb, cmd); } } if (rc) pb_packs(&ugdb->g_pbuf, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->g_ibuf; int todo = ugdb->g_ilen; if (d_echo) printk(KERN_INFO "=> %.*s\n", ugdb->g_ilen, ugdb->g_ibuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: // XXX: Ctrl-C sends chr = 3, not implemented. printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->g_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->g_err = -EPROTO; case '+': break; case 0x3: ugdb_c_all(ugdb, "S02"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->g_no_ack) pb_putc(&ugdb->g_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->g_ilen = todo; if (todo && cmds > ugdb->g_ibuf) memcpy(ugdb->g_ibuf, cmds, todo); } static struct ugdb *ugdb_inifin(struct ugdb *ugdb) { int err = 0; if (ugdb) goto dtor; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; pb_init(&ugdb->g_pbuf); INIT_LIST_HEAD(&ugdb->g_attached); init_waitqueue_head(&ugdb->g_wait); return ugdb; dtor: kfree(ugdb); put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_inifin(NULL); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { struct ugdb *ugdb = file->private_data; ugdb_detach_many(ugdb, -1, -1); ugdb_inifin(ugdb); return 0; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (count > PACKET_SIZE - ugdb->g_ilen) { count = PACKET_SIZE - ugdb->g_ilen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->g_ilen); } if (copy_from_user(ugdb->g_ibuf + ugdb->g_ilen, ubuf, count)) return -EFAULT; ugdb->g_ilen += count; process_commands(ugdb); *ppos += count; return count; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->g_err) return ugdb->g_err; if (!pb_size(&ugdb->g_pbuf)) { int err = ugdb_wait_for_rc(ugdb); if (err) return err; } if (pb_size(&ugdb->g_pbuf) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(&ugdb->g_pbuf), count); } count = pb_copy_to_user(&ugdb->g_pbuf, ubuf, count); if (count > 0) *ppos += count; return count; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains. return 0; } static const struct file_operations ugdb_f_ops = { .write = ugdb_f_write, .read = ugdb_f_read, .open = ugdb_f_open, .release = ugdb_f_release, .unlocked_ioctl = ugdb_f_ioctl, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From pontoideias at gmail.com Mon Jul 19 20:54:09 2010 From: pontoideias at gmail.com (Ponto Ideias) Date: Mon, 19 Jul 2010 21:54:09 +0100 Subject: Ponto Ideias Message-ID: <20100719205410.4F6ED1E1C39@av-out3.netvisao.pt> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: hex0.jpg Type: application/octet-stream Size: 142923 bytes Desc: not available URL: From roland at redhat.com Mon Jul 19 22:59:25 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 19 Jul 2010 15:59:25 -0700 (PDT) Subject: gdbstub initial code In-Reply-To: Oleg Nesterov's message of Monday, 19 July 2010 18:25:25 +0200 <20100719162525.GA22027@redhat.com> References: <20100712183729.GA8850@redhat.com> <20100713055516.7236740842@magilla.sf.frob.com> <20100713133550.GC31646@redhat.com> <20100714233754.GA26687@redhat.com> <20100716074746.C063C4C853@magilla.sf.frob.com> <20100716151128.GA8876@redhat.com> <20100719162525.GA22027@redhat.com> Message-ID: <20100719225925.953B440840@magilla.sf.frob.com> > At first I tried to support both multiprocess and !multiprocess > modes, but this needs too many "unnecessary" code which I'd like > to avoid, at least now. So this version requires "multiprocess+" > in qSupported, otherwise "target extended-remote" fails. > > Please let me know if we need both modes. No, that is fine. We aren't trying to make it a universal implementation of the gdb remote protocol in all variants to work with all gdb versions of the past. We're just trying to make it work well with current/future gdb. Thanks, Roland From rtj at cv.com Tue Jul 20 07:04:41 2010 From: rtj at cv.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Tue, 20 Jul 2010 15:04:41 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsssm5usH3s8zTxbuv0+u5qdOmycy53MDt?= Message-ID: <201007200704.o6K74f8J004515@mx1.redhat.com> utrace-devel??????????????? ?????2010?7?21-22??? ?????2010?7?27-28??? ?????2010?8?3-4? ?? ????: 2500?/ ?????????????????? ?????????????????????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ????? ??????????????? ???????????? ?????????????? ????????????? ????????????? ?????????? ??????????? ?????????????? ??????????? ---------------------------------------------------------------------------------------- ???? ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? -------------------------------------------------------------------------- ?????????? --- ?????????????1986????Gerber????????? Michigan State University (???????) ????????????,?????Heinz(??) ???????????????????????????????????????????? ????????????2000???,????????????????????????,?? ?????500?????????????,???????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????????????????? ?????????????,?????????,??,? ??????????,?????,???????????????????????????? ?????,??????????????,????????????????????? ?????????????????????????????????????? ??????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From jap at qweg.com Tue Jul 20 08:37:10 2010 From: jap at qweg.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Tue, 20 Jul 2010 16:37:10 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsuanTpsnMudzA7bywxrfWyrncv9g=?= Message-ID: <201007200837.o6K8b6iq027783@mx1.redhat.com> utrace-devel?????????????????????????????? ??????????2010??7??24--25??----???? ???? ??????????2010??7??30--31??----???? ???? ??????????????????????????????????????????????????????????????????SQM???????????????????????????????? ?????????????????????????????????????????????????? ??????????2600??/??????????????????????????2?????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? --------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????SQM???????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????SQE???????????????????????????????????? ================================================================================== ???????? ?? ????????????????SQM???????????????????????????????????????????????????? ?? ????????????????????????????????????????SQE?????????? ?? ?????????????????????????????????????????? ?? ????SQM?????????????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????? ====================================================================================== ??????????????????--?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????? ????????????????????MBA???????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????SPC?? DOE??MSA??FMEA?? TQM??QFD???? ??????????????????,?????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????2000- 2004??????????????????????/????/????????????????????????????????: ???????????????????????????????? ??????????????????????????????????????????????????ISO9001??2000???????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????.???????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????SQM???????????????? (TQM)??????????????????????????????????????????????????????????????????????????????????600?????? ????????4000???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????,???????????????????????????????????????????????????????????????????????? ??????????????????????(TQM)???????????? ??????/????????????????????????,?????????????????????????????????????????????????????????????????? ???????????????????????????????????? ====================================================================================== ?????????? ????????????????SQM?????? ??????????????????????????SQM ?????????????????????????????????????????? ??????SQE?????????????????????????????????????????? SQM???????????????????????????? ?????????????????????????????????? ?????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????? ???????????????????????????????????????????? ??????????????????5R?????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????? ???????????????????? ???????????????????????????????????????? ?????????????????????????????????? APQP?????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ??????????ECN??????????????????????POKA-YOKE???? ?????????????????????? ???????????????????????????????????????????????????? ?????????????????????????????????????????? ????SQE??SQM?????????? ???????????????????????????????????????????? ??????????AQL??AC??RE??C=0 ????????????????????IQC??IPQC??QC??TQC??FQC??QA??OQC?????????? ?????????????????????????????????????? ?????????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????CAR??8D ?????????????????????????? ?????????????????? ?????????????????????????????????????????????? KPI?????????????? ?????????????????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????????? ?????????????????? ?????????????????????????????????????????????????????? SQM??????????????????????????????????????????????PDCA ?????????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????????????????????????????? ?????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????? ?????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ????????QMS?????????????????????????????? ?????????????????????????????????????????????????????????? ????SQM?????????????? ????????????????????????????????????????????????????????FMEA ?????????????????????????????????? ????QC???????? QCC??5Why??8D??SPC ????????????????????????????????????????TPM??TQM ????SQE???????????????????????????? SQE???????????????????????????????????????????? ?????????????????????????????????????????????????????????? ???????????????????????????????????????????? SQE?????????????????????????????????? ???????????????????????????????????????????? SQE???????????????????????????????????? ====================================================================================== ????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From jguansheya at vip.163.com Tue Jul 20 20:07:01 2010 From: jguansheya at vip.163.com (2010-07-21 04:07:00) Date: Wed, 21 Jul 2010 04:07:01 +0800 Subject: =?gb2312?B?1+7Qwreiz9ajusjnus4utKnXxcuv0sLX+NTas/jXwLHfx+HLyb/s?= =?gb2312?B?y9m1xNesLseuo78=?= Message-ID: <20100721040710524383@vip.163.com> An HTML attachment was scrubbed... URL: From wmj at xaj.com Wed Jul 21 03:31:33 2010 From: wmj at xaj.com (=?GB2312?B?16rQ6MfzyMvUsQ==?=) Date: Wed, 21 Jul 2010 11:31:33 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0dC3os3FttO9qMno0+u8pMD4?= Message-ID: <201007210331.o6L3VUmT002511@mx1.redhat.com> utrace-devel???????????????????????????????????????? ??????????2010??7??29--30?????? ???? ??????????2010??8??17-18?? ???? ???? ??????????????????????????????????????????????????????/??????????/?????????????????????? ??????????2600??/?????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????chinammc2010 at 126.com?????? ---------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? 1???????????????????????????????????????????????????????????????????? 2????????KPI ??????????????????????KPI ???????????????????????????? 3?????????????????????????????????????????????????? 4???????????????????????????????????????????????????????? 5???????????????????????????????????????? 6???????????????????????????????????????????????????????? 7???????????????????????????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????? 11???????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? ================================================================================== ???????? 1?????????????????????????????????????????????????????????????????????????????????????????? 2?????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????? 4???????????????????????????????????????????????????? 5????????????????????????????????????????KPI ???????????????????????????? 6??????????????????????????????????????????PBC?? 7???????????????????????????????????????????????????????? 8???????????????????????????????????????????????????????????????????????????????????? 9??????????20 ?????????????????????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ?????????????????? ???? ?????? ?????????????????????????????????????????????????????????????????? ???????????????????? ==>?????????????????????? ??????????????????????1999???????????????????????????????????????????????????????????????????????? ==>???????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????20???????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? ????????????????????????300??????????????????????????????20??????????????????????????????????????3000?????????? ????????????????????????????????????????????92%????,????????????????????????????????????????????????????,?????? ???????????????????????????????????????????? ====================================================================================== ???????? ???? ?????????????????????? 1. ?????????????????????? a) ?????????????? b) ?????????????? c) ?????????????? d) ???????????? e) ???? 2. ??????????????????PAC??PMT??PDT?? 3. ???????????????????? a) ?????????????????????????????????????????????????????? b) ?????????????????????????????????????? c) ?????????????????????????????????????????????? d) ?????????????????????????????? e) ?????????????????????????????????? f) ?????????????????????????????????? g) ???????????????????????????????????????? h) ?????????????????????????????????????????????? 4. ???????????????????????????? a) ?????????? b) ???????? c) ???????? d) ???????? e) ?????????????????????????????????????????????????????????? 5. ???????????? a) ???????? b) ???????????? c) ???? 6. ???????? ???? ???????????????????????????????????????????? 1. ???????????????????????????? a) ?????????????????????? b) 18???????????? c) ???????????????????????????? * ?????????? * B??E??I????????????????????BEI???????????? d) ???????????????????????????????????????????????? * ???????????????????????????????? e) ?????????????????????????????? * ???????? * ???????? * ?????????? * ???????????? * ?????????????? * ???? 2. ???????????????????????????????? a) ?????????????????? * ???????? * ???????? * ????????????????QA b) ???????????????????????? c) ?????????????????????????????????????? d) ?????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????????????? 2. ???????????????????????????????????????? 3. ???????????????????????????? a) ???????????????? b) ?????????????????????????????????????????? c) ?????????????????? 4. ?????????????????????????? 5. ?????????????????????? 6. ?????????????????????? a) ???????????????????????? b) ????????????????????????????????????????KPI?? 7. ?????????????????????? a) ?????????? b) ?????????????? 8. ???????????????????????????? a) ???????????? b) ?????????????????????????? c) ???????????????????? 9. ?????????? a) ???????????????????????????????????????????? ???? ????????????????????????????????KPI ???????? 1. ????????KPI ???????????????????? 2. ????????????????????????????????????KPI ???? 3. ????????KPI ?????????????? 4. ????????KPI ?????????? a) ???????????????? b) ???????????? 5. ????????KPI ??????????????????I??T??Q??C??S?? 6. ??????????KPI ?????? a) ????????KPI ???? ???????????????????????????????????????????? b) ????????KPI ????????????????????????????????????QA?????? c) ??????????????KPI ????????????HR?????????????????????????? 7. ????????KPI ?????? 8. ?????????????????? a) ???????????????????????????? b) ?????????????????????? c) ??????????????KPI ???????????? d) ?????????????????????????????????????????????? 9. ?????????? a) ????????????????????KPI ?????????????????????????????????????????????? b) ??????????KPI ???????????????????????D?D??????????????PCB ???? ???????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????? a) ?????????????????? b) ?????????????????????????????????????????????????????? 3. ?????????????????? a) ?????????? b) ?????????????????? c) ???????? d) ?????????????? 4. ???????????????????????D?D????????????PBC a) ??????????WINNING?? b) ??????????EXECUTION?? c) ??????????TEAMWORK?? 5. ????????????????PBC ?????????????? 6. ????????????????????????????????PBC 7. ?????????????????????????????? 8. ??????????????????????????PIP?? 9. ?????????? a) ????????????????????????PBC???????? b) ????????????????????????PIP???????? ???? ?????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????????? 3. ???????????????????????????????????????? a) ?????????? b) ?????????? c) ?????????? d) ?????????? 4. ?????????? a) ???????????????????????????????????????????? ???? ???????????????????????????? 1. ?????????????????????????????????????????????? a) ?????????????????????????????????????????? b) ???????????????????????????????????????? 2. ??????????????????????????????????????????HR???????? 3. ?????????????????????????????????????????? 4. ???????????????????????????????????????????????????? 5. ???????????? a) ?????????????????????? b) ???????????????????????????????????????????????????????????? c) ???????????????????????????? d) ?????????????????????????????????? 6. ???????????????????????? a) ?????????????? b) ???????????????????????????????????????????????????????????????????? 7. ?????????????????????? a) ?????????????? b) ?????????????????????????? 8. ???????????????????????????????????????????????? 9. ???????????????????????????????????????????? a) ???????? b) ???????? c) ???????????????? 10. ???????????????????????????????????????? 11. ?????????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????? 2. ?????????????????? a) ?????? b) 5??/10???????? c) ?????? d) ?????? e) ???? f) ???? 3. ???????????????????????????????????????????? 4. ?????????????? a) ??????/?????? b) ?????? c) ?????? d) ?????? e) ?????? 5. ?????????????????????????????????????? 6. ???????????????????????????????????????????????????? -------------------------------------------------------------------- ??????????????????????????????????????????????????????????????020-62351156?? ?????????? ?????? ?????? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638?????? From lifuling67125 at tom.com Wed Jul 21 15:54:18 2010 From: lifuling67125 at tom.com (=?gb2312?B?bGlmdWxpbmc2NzEyNQ==?=) Date: Wed, 21 Jul 2010 23:54:18 +0800 (CST) Subject: =?gb2312?B?LdPKvP7Su7fdLTk3NDc=?= Message-ID: <4C47182A.00027F.07497@cnapp32> ????: ???????????????????????????????????????????V???????????????????I. ???????U?? ???????h???????????H?????????I???I,????????????????????????????????????????????????.????????; ?????p?????????c????.?????????????????????????????? QQ ?????? ??????:????{??} ?????? 135-5486-2829 QQ: 534580989 ?? ???????_??????!?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From news.july at naviproglobal.com Wed Jul 21 16:01:35 2010 From: news.july at naviproglobal.com (NaviProGPS-USA) Date: Wed, 21 Jul 2010 18:01:35 +0200 Subject: GPS Ad Order Form For Utrace Devel, Redhat Message-ID: You have just a few days left to enabIe YOUR BUSINESS INFORMATION to display on GPS devices & Mobile Phones for the low monthly fee of $8.95 This discount for updating the gps richpoi database ends on July 30, 2010! Supported platforms Mobile phones/ applications: Motorola, Nokia, Samsung, SonyEricsson, iPHONE, Google Maps, Garmin Mobile, Garmin XT, TomTom GO, iGO 2006, iGO 8, iGO amigo GPS PNA: Garmin, Tomtom, NNG Systems: Airis, Altina, Apontador, ASUS, AudioMedia, Audiovox, Autovision, Aviton, BendixKing, Blaupunkt, Caska, Clarion, CNS, Crypton, Cyclone, DreimGO, Ergo, Evolve, Exper, Explay, Geographic, Globalsat, GlobWay, GPS Aquarus, GPSTURK, Guepard, H-Buster, HP, Hyundai, iconX, iFind, Invion, Isuzu, Jensen, JoyPlus, Macrom, Mando, Mappy, MyGuide, Mypilot, Navigo, Navitech, NavOn, NBX, Next, Nextar, OCN, Orion, Phonocar, Piranha, Pocket Navigator, P?sitron, Prestigio, QUE, Ramar, Reaction, Renault, RoadCommander, Rosen, Scania, Scott, Shturmann, Siga-me, Skyway, Stromberg Carlson, takeMS, Telefunken, TELE System, Tilborg, Toshiba, Unicars, Uniden, Vector, Vendeka, VMS, Wondeproud, XZENT, Zenec LEARN MORE: naviprousa.com/services_online.html NaviPro U.S. Llc. - Customer service: 888-524 9365 begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting begin_of_the_skype_highlighting??????????????888-524 9365??????end_of_the_skype_highlighting Customer support: support at naviprousa.com 8835 SW 107 AVE, # 281, MIAMI, FL 33176, www.NaviProUSA.com To stop receiving these emails:http://massmail.naviprointernational.com/unsubscribe.php?M=9578254&C=c0e377865adba17b68ba03f00e9cd1de&L=542&N=564 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 98e535c6f62e833e1abd4c02763aff60 Type: image/jpeg Size: 24131 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: f9a3f4562b5859211a8cc675ccc41123 Type: image/jpeg Size: 77974 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 538f44590ed77081ba57a4c016c51177 Type: image/jpeg Size: 17937 bytes Desc: not available URL: From liuxing1021 at 21cn.net Thu Jul 22 18:48:00 2010 From: liuxing1021 at 21cn.net (liuxing1021 at 21cn.net) Date: Fri, 23 Jul 2010 02:48:00 +0800 (CST) Subject: =?UTF-8?B?5bq35YGl77ya55S35oCn5oCn5LiK55i+55yf55qE5b6I6YGt572qIA==?= Message-ID: <12446693.73131279824480258.JavaMail.root@pay4> An HTML attachment was scrubbed... URL: From charlesjihadi at voila.fr Thu Jul 22 05:18:41 2010 From: charlesjihadi at voila.fr (From: Mr.Charles Jihadiih) Date: Thu, 22 Jul 2010 07:18:41 +0200 Subject: Greeting From Mr. Charles Jihadiih Message-ID: Greeting From Mr. Charles Jihadiih Attention: Please!!! I am Mr. Charles Jihadiih Accounts department. With the groups African Development Bank (A.D.B) I am writing to request your assistance to transfer the sum of $8.5 milion United States dollars into your accounts. The above sum belongs to one our deceased customer who died along with his entire family in a during Iraqians war and his account has been dormant. After my further investigation, I discovered that deceased customer died with his next of kin and according to the laws and constitution guiding this banking institution stated that after the expiration of some years, if no body or person comes for the claim as the next of kin, the fund will be channel into national treasury as unclaimed fund. Because of the static of this transaction I want you to stand as the next of kin so that our bank will accord you the recognition and have the fund transfer to your account. The total sum will be shared as follows: 50% for me, 50% for you and expenses incidental occur during the transfer will be taking care of by both of us. The transfer is risk free on both sides hence you are going to follow my instruction till the fund transfer to your account. More details information with the text of claiming application form will be forwarded to you to breakdown explaining comprehensively what require of you. Thanks. Mr. Charles Jihadiih From liuxing1012 at 21cn.net Thu Jul 22 22:56:50 2010 From: liuxing1012 at 21cn.net (liuxing1012 at 21cn.net) Date: Fri, 23 Jul 2010 06:56:50 +0800 (HKT) Subject: =?UTF-8?B?5oCn54ix5ZCO5ZCD6bih6JuL5Yqp4oCc6KeE5aSN5YWD5rCU4oCdIA==?= Message-ID: <26270556.27491279839410398.JavaMail.root@pay3> An HTML attachment was scrubbed... URL: From axefc at gymo.com Fri Jul 23 08:51:33 2010 From: axefc at gymo.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Fri, 23 Jul 2010 08:51:33 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsvvay39XftcSyxs7xudy/2A==?= Message-ID: <201007230851.o6N8p5Fk008133@mx1.redhat.com> utrace-devel???????????????? ??????????2010??08??06-07?? ???? ??????????2010??08??20-21?? ???? ??????????3200 /???????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ?????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??????????????????????????3.5?? ???????????????????????????????????? ?????????????????????????????? ???????????????????????????????????????? ????????????????????????????????????????????????????????????2????????1???????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????? 1?????????????????????????????????????????????????????????????????????????? 2???????????????????????????????????????????? 3???????????????????????????????????????????????????????????????? 4???????????????????????????????????? 5?????????????????????????????????????????? 6?????????????????????????????????????????????????????? 7?????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????? ???????????????????????????? ?????????????????????????????? ???????????????????????????????????? ----------------------------------------------------------------------------------------- ????????: ?????????????????????????????? ?????????????????????? ???????????? ???????????? ?????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????????????????? 1.?????????????????????? 2.?????????????????????????????????????????? -?????????????????? -?????????????????? 3.???????????????????????????????????? -?????????????????? 4.?????????????????????? -?????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.????????????????????---?????????????? ???????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????????? 1.?????????????????????? 2.?????????????????? 3.????????????5R???? 4?????????????????????? 1?????????????????? - ?????????????? - ?????????????????? - ???????????????????? - ???????????????????? 2?????????????????? 3?????????????????? 4?????????????????? ???????????????????????? 1.???????????? - ???????????? - ???????????? - ???????????? 2.???????????????????? 3.?????????????? - ???????????????????????????? - ???????? 4.????????????????????---?????????????? ????????????---?????????????? 1.???????????? - ?????????????????? - ?????????????????????? - ???????????????? 2.???????????????????? - ?????????????????????? - ?????????????????? - ?????????????????? - ?????????????????????? 3.?????????????????? - ?????????????????????????????????????? - ???????????? 4???????????????????????? 1?????????????????? ?????????????????????????????????????????? ---?????????????? 2???????????????????????? 3???????????????????????? -??????-???????????????????????????? -??????-???????????????????????????? -?????????????????????????????????? ???????????? ???????? ???????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? 1.?????????????????? 2.?????????????????????????????? 3.???????????????? 4.?????????????????????????????????? 5.?????????????????? 6.?????????????????????????????? ?????????????? ???????????????????? ?????????????????? ----------------------------------------------------------------------------------------------------- ???????????????? ???????????????????????????? ?? ???????????????????????????? ?? ?????????????????????? ?? ?????????????????? ?? ?????????? ?? ?????????????????????????????? ?? ?????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????IT??????????????????50???????????????????????????????????????????????????????????????? ????C2C??????????????????12345??????????????????????????????????????????????????????6R?????????????? ????????????????????656?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????60????????????????????????????????????????????????????50%???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????x?????????????????????????????????????????????? ???????????? ???????????????????? ???????????????????? ???????????????????????????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From davidwest19 at att.net Fri Jul 23 12:37:05 2010 From: davidwest19 at att.net (David West) Date: Fri, 23 Jul 2010 05:37:05 -0700 (PDT) Subject: CAN YOU SUPPLY THE PRODUCT TO US. Message-ID: <509928.25835.qm@web83908.mail.sp1.yahoo.com> CAN YOU SUPPLY THE PRODUCT TO US. Dear Sir, I hope this mail meet you in good health. There is this product I suggest you may be able to supply to our company.? The name of the product is Diamond Misers use in Diamond Companies. I use to supply it to my company directly from Dubai UAE. I use to buy it and supplies to my company without my company knowing actual price of the product. Now I have been transfer from the department that make it easier for me .The new person that took over my position in that department did not know the seller of the Product. I will introduce you to him as the seller of the product so that they can buy from you directly after you might have buy from the original seller. ? This is my reason of contacting you, if you will be able to be supplying the product to my company on regular bases as needed. The supply or transaction has to be well handled, since it is going to be a continue transaction between you and our company, it will be of a good benefit to us. This is how you should handle the business. Please, don?t allow My Company Director to know the seller and don?t let the seller to know My Company Director, because if they know each other, both of us will not get anything from the business anymore, both of them will be handling the business by themselves, and for me I will have a big problem with my company because I don?t want them to know how much I use to buy the product from the seller. ? My Company need about 150 to 200 cartons, it's not under most you supplier the quantity my Company need. you can start by 20 or 30 cartons depending on the cash you hold at hand and supply to my Company. My Company will pay you cash on delivery then you will go back and buy the remaining from the seller and supply to my Company. When you buy in Dubai my office can send one of our company. You will buy per Carton from the seller at 1carton contains 12bottles one bottle's $200 and supply to my? Company? at $400 per bottle, my Company will? pay you cash, Please let me know if it will be possible for you or your company to be supplying this product for my company. Yours faithfully Mr. David West. -------------- next part -------------- An HTML attachment was scrubbed... URL: From crm507 at hotmail.com Fri Jul 23 15:09:38 2010 From: crm507 at hotmail.com (Carlos roman) Date: Fri, 23 Jul 2010 17:09:38 +0200 Subject: =?utf-8?B?54m55Yir6YeN6KaB77yB77yB77yBYw==?= Message-ID: ?????? ????????,"?????????????????? ?????????????? ???????????? ???????????? ??????????? ??????????????? ?? ??????????????????????????????? 1. ???????????????2980?????????????? 2. ????????????? ?????????? ?????? 3. ????6?8?????????????DVD 4.??????????6800????????????????DVD 5.??????? ??? ?????????????14????????????58000??????????????? ??????? ??????? ps??????10??????????????? _________________________________________________________________ Hotmail prepara novedades y sorpresas en breve, ?estate atento! http://explore.live.com/windows-live-hotmail -------------- next part -------------- An HTML attachment was scrubbed... URL: From brachszgo at sogou.com Fri Jul 23 18:54:41 2010 From: brachszgo at sogou.com (brachszgo at sogou.com) Date: Fri, 23 Jul 2010 18:54:41 GMT Subject: =?utf-8?b?5L2g5oOz6Lq65Zyo5bqK5LiK6L+Y6IO96LWa6ZKx5ZCX77yfKuavj+S4gA==?= =?utf-8?b?5Y+R5aWL5Yqq5Yqb55qE6IOM5ZCO77yM5b+F5pyJ5Yqg5YCN55qE6LWP6LWQ?= =?utf-8?b?44CCKg==?= Message-ID: <1279911281.3356f2209f26498c8ac90816cf21a0a4.brachszgo@sogou.com>               ??????        jlnkpe313         ????????????????????????????????????????????????        oicumf207       ??????????????????????????????????????????????    ??????????????????????????(???N???????)?      ??????????????????????????????????????????45???????????????????????????????????????????????????11????????????????????????45???????????????????????? ???????????????????????     ????????????????????????????? ????????????????????????  pftfsk055            http://www.yingxiaomijue.com  ggddym051 ????????????????????????         ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????  jnsaon474           ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? anlwec  nnudkh621   ????????????????????  wdlwql484 NO  NO  NO  ???   ???????????    pttspa701 ??????????????????100%???? ??????  7310 ????????????????   1????3???? 248???????? ????? ????? ??????  7650 2??????????????????????  nynbwu556 3?7 ??????????????????? ?  iosqwu304 4??????????????????????????????  anlawo877 5????3???????????????14???1000????240000? ?  5119 6?????????????????? ???????????   7?????????????????????????????????   8?9 ????????? ????????????????????   ?????????      ?????????????????????????????????????????????????  dtfryp531 ??????????????????????????????? ??????????????????????? ?????????????????????????????????? ???????????2?2??????????????  ofejis406 ??????????????? ??????? www.yingxiaomijue.com   ???????????????????????13564693672   5252 ????????????????????????                             ?????????   ?????????????????????????   ps????????3????????????????????? 48 ?????????????????????????????????????????????????????????????????????????       nmulbr860         www.yingxiaomijue.comsbpmxm088           PPS???????????????????????????100??????????????????????50?????????????72????????????????       ?????????????????????????????????????????????????????               www.yingxiaomijue.comrbrdrd354   PPPS?????????????????????????????72???????????????????????  omlwkw763 PPPPS???????????????????????????????????????????????????????????????????????????????1000??????  jymwsm424????????www.yingxiaomijue.com         -------------- next part -------------- An HTML attachment was scrubbed... URL: From tel.inters.p.a at email.it Sat Jul 24 09:39:00 2010 From: tel.inters.p.a at email.it (A .Baloteli) Date: Sat, 24 Jul 2010 11:39:00 +0200 (CEST) Subject: Winning Notification!!! Message-ID: <63498.151.82.175.31.1279964340.squirrel@www.igp.gob.pe> Hello, I'm connecting with you inrespect to confirm if you are eligible enough to go into business with me. I have a proposition and i'm in need of a partner. For more talks regarding this project, i can be reached at the below email address (srafa at dmot-pot.info). Sincerely Yours, Dr. M. Al Shurafa From fmonte at sympatico.ca Sat Jul 24 11:37:19 2010 From: fmonte at sympatico.ca (rczyebl) Date: Sat, 24 Jul 2010 19:37:19 +0800 Subject: =?gb2312?B?z/pfytstvqtf06Jgt+gtv/HRtS3Bty9sag==?= Message-ID: <20100724193729024081@sympatico.ca> ?? ?? ?? ??2?????? ?? ???? ?? ?? ??: 2010??7??24-25?? ?? ?????? ?? ?? ??: 2010??7??31-8??01?? ?? ?????? ?? ?? ??: 2010??8??14-15?? ?? ?????? ?? ----------------------------------------------------------------------------------- ??-??-??-?????????????????????????????????????????????????????????????????? ----------------------------------------------------------------------------------- ??-??-??-???? Judge??????????????????????????????????????????????????Harvard???????????????? ????Stanford??????????????.????judge??????????????????????????????????????judge???? ?????????????????????????????????????????????????????????????? ?D?D?D?D?D?D ???????????????? 1. ???????????????????????????????????????????? 2. ???????????????????????????????????????????????????????? 3. ???????????????????????????????????????? 4. ???????????????????????????????????????????? 5. ???????????????????????????????????????????????????? 6. ???????????????????????????????????????? 7. ???????????????????????????????????????????????????? 8. ???????????????????????????????????????????????????????? --------????????????????????????2?????????????? ??-??-??-???? 1. 2??1????????36??????????17?????????????? 2. ???????????????????????????????????????????? 3. ?????????????????????????????????? 4. ???????????????????????? ? ???????????????????????????????????????? ? ???????????????????????????????????? ? ?????????????????????????????????????????????????? ------------------------------------------------------------------------------ ??-??-??-??: ??????????????????????10?????? 1. ?????????????????????? ?? ?????????? 2. ???????????????????? ?? ?????? 3. ???????????????????????? ?? ???? 4. ?????????????????????? ?? ???? 5. ???????????????????????? ?? ???? 6. ???????????????????? ?? ???????? 7. ?????????????????????? ?? ???? 8. ?????????????????????????????? ?? ???? 9. ?????????????????????????? ?? ???? 10. ?????????????????????? ?? ?????? ??????????????????9?????????? 1. ???????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2. ?????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3. ???????????????????????? ???????????????????????????????????? 4. ?????????????????????????? ???????????????????????????????????????????? 5. ???????????????????????????????????? ???????????????????????????????????? 6. ???????????????????????? ???????????????????????????????????????? 7. ???????????????????????????? ?????????????????????????? 8. ???????????????????????????????? ?????????????????????????????????????? 9. ?????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ? ???????????????????????????????????????? ? ???????????????????????????????? ? ?????????????????? B???????????????????????????? 1. ?????????????????????????? 2. ???????????????????????????????? 3. ?????????????????????????????????? 4. ?????????????????????????????????? 5. ?????????????????????????????? 6. ???????????????????????????? 7. ?????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ? ??????????????????????????????! ? ???????????????????????????? ? ???????????????????????????? ???????????????????????????????? ? ??????3???????? ? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ? ??????????????????????9???????? ? ??????????????????????????5???????? ? ??????????????????????4???????? ? ????????????,????????????3??????? ? ??????????,??????????4??????? ?????????????????????????????????????? ? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ? ???????????????????????????????????? ? ????????????????????4???????? ? ????????????????6?????? ? ???????????????????????????????? 2???????????????????? ? ?????????????????????????????????????????????? ? ?????????????????????????????????????????????? ? ???????????????????????????????? ? ??????????????6?????????? ? ?????????????? ? ???????????????????????? ? ???????????????????????? ???????????????????????? 1. ?????????????????????????????????? 2. ?????????????????????????????????????? 3. ???????????????????? ------------------------------------- ????????: A.??????????????????????,???????????????? B.????????????????????????????????????????????.????????????????????. ------------------------------------------------------------------------------- ??-??-??-??: ?? ?? ?? ?? ? ???????????????????????????? ? ?????????????????????????????????? ? ?????????????????????????????????? ? ???????????????????????????????????????? ? ????????.????????.????????EMBA?????????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????????? ????????????????????,??????????????????,?????????????????????????????????????????? ??????????????????????????????????????????????????. ?????????? ?????????????????????? ???????????????????? ???????????????????????? ???????????????? ?????????????????? ???????????????????????? ?????????????? ?????????????????????? ????????/????????????/????????/????????/????????/????????/??????/????/????????/???? ????????/????????/????????????/????????/????????????/????????????/????????????/???? ??????/????????????/??????????/??????????????/??????????/????????????/????????????/ ????????/????????/????????/????????/??????????????/????????/????????/?????????????? ????????/?????????????? --------------------------------------------------------------------------------- ??-??-??-?????????????????????????????????????????????????????????????????? ??-??-??-????2470??/?? (2????,1???? ????,??????????,??????,??????) ??-??-??-??: 020-83692894 ?? 83664364 ??-??-?? ??-??-??-?????? ?? ?? ?? ?? ?? --------------------------------------------------------------------------------- ???????????????? ?? ?? ?? ?? ?? ???????????????? ????????????????????????????huangwts at 163.com ????????????020-83664364 ??-???Q-?????W-?T??-?????? ?? ?? ??2???????? ???? ????????-?o????-??: ?? ?x ???? ???? ?c??2010??______??______?? ???? ?? ???? ?? ???? ?? ???? ?? ???????????????????????????????????????????????????????? ???????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? ?????????????????????????????????????????????? ?????????????????? ?? ?????????????????????? ?? ?? ?? ?????????????????????????????????????????????????????????????? ??,??,??,???????? ?x ?? ?? ?? ?? ??1???F ?? ??2???? ?? ??-??-??-??: 020-83692894 ?? 83664364 ??-??-?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From lxr1003 at 21cn.net Sun Jul 25 13:20:35 2010 From: lxr1003 at 21cn.net (lxr1003 at 21cn.net) Date: Sun, 25 Jul 2010 21:20:35 +0800 (HKT) Subject: =?UTF-8?B?55S35oCn5Lus5oCO5LmI5a6J6Z2W5aW95L2g55qE5py65omL6IWVIA==?= Message-ID: <31664739.74041280064035469.JavaMail.root@pay3> An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Tue Jul 27 01:21:03 2010 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Mon, 26 Jul 2010 22:21:03 -0300 Subject: Sonhos do Meu Pai: O presente dos sonhos do seu pai, a precos especiais voce encontra aqui Message-ID: <9a92c0386ce1d81902a7e8eb001e47c0@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From bedpost at floorpride.net Tue Jul 27 14:06:40 2010 From: bedpost at floorpride.net (Milas Cassetty) Date: Tue, 27 Jul 2010 16:06:40 +0200 Subject: O great to trouble himself with the affa Message-ID: A non-text attachment was scrubbed... Name: visibly.png Type: image/png Size: 21146 bytes Desc: not available URL: From weierdyzj at 21cn.com Tue Jul 27 16:11:20 2010 From: weierdyzj at 21cn.com (weierdyzj at 21cn.com) Date: Wed, 28 Jul 2010 00:11:20 +0800 (CST) Subject: =?UTF-8?Q?7345_=E9=94=80=E5=94=AE=E4=B8=BB=E7=AE=A12=E5=A4=A9?= =?UTF-8?Q?1=E5=A4=9C=EF=BC=81kkqcmr415?= Message-ID: <12468280.619041280247080982.JavaMail.root@webmail6> An HTML attachment was scrubbed... URL: From aed at ofce.com Wed Jul 28 01:42:02 2010 From: aed at ofce.com (=?GB2312?B?x+vXqs/gudiyv8PF?=) Date: Wed, 28 Jul 2010 09:42:02 +0800 Subject: =?GB2312?B?0MK3qM/CtcTIy8Gm18rUtLncwO3WxrbIyei8xg==?= Message-ID: <201007280142.o6S1fwt9009651@mx1.redhat.com> ??????????????????? ?????2010?7?30-31? ?? ?????2200/?????????????????? ???????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------- ??????????????????????????????????????2008?1?1????? ?????????????2008?5?1?????, ??????????????????????? ?????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????? --------------------------------------------------------------------------------------------- ???? ??????????? ??????????????? ??? ??????? 1?????????????? 2?????????????? 3??????????????? ??? ????? 1.??????????????????; 2.??????????????????????????; ??? ????????????????? 1?????????????????????????; 2??????????? ??? ??????????????? 1???????? 2??????????????? 3??????????????????? 4??????????????? 5????????????????????? ?????????????? 1????????????????????? 2???????????? 3??????????????????? 4?????????????????? 5??????????????????????????????????????? 6??????????????? 7????????????? 8??????????????????? 9????????????? 10???????????????????????????????????? ??????????????????? 1?????????????????????????9??? 2?????????????????????????????12??? 3??????????????? 4??????????????? ?????????????? 1???????? 2??????? 3??????? 4?????????? 5???????? 6??????????????? ????????????? ????????????????????????????????????? ??????????????????? ??????????????????????????? ????????????????????? ?????????????????? ???????????????? ??????????????????????? ????????????????????? ??????????????????????????? ???????????????????????? ??????????????????? ?????????????????? ????????????????? ?????????????????????????? ?????????????? ?????????? ??????????????????????? ???????????? ??????????????????????????? ??????????????????????????? ????????????????????????????????????? ???????????????????????????????????? ???????????????????????????????? ??????????????????????????? ???????????????????? ???????????????????????????? ????????????????????????? ???????????????? ??????????????????????? ????????????????????? ????????????????????? ????????????? ??????????? ?????????????? ???????????????? ???????????????? ?????????????????????? ??????????????????? ???????????????? ??????????????????????? ??????????????????? ??????????????????? ????????? ????????????? ???????????? ??????????????? ??????????? ??????????? ????????????? ?????????? ??????????????? ????????????? ??????????????? ???????????????? ????????????????????????? ?????????????????? ???????????????????????? ???????????? ?????????? 1.?????? 2.?????? 3??????????? 4??????????? 5?????????????? 6????????? 7????????? 8??????? ????????????? a)????????? b)??????? c)????????? d)????????? --------------------------------------------------------------- ?????????????????????????? ? ?????????????????????????????????????? ?????????????????????????????????????????????????? 2007????????????????????????????95%??????????????????? ????????????????????????????????????????07????????? ??300????????1500? ?????????95%????????????1300???????????????? ?????????????????????????????????????????????????? ??????????????????????????????1000????????????????? ?????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ?????????????????? ????????????????????????SONY??????????????PHILIP????????? ???????????????????????????????????????????????????? HP?????????????????? =============================================================================== ??????????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From bvu at qwex.com Wed Jul 28 14:17:31 2010 From: bvu at qwex.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 28 Jul 2010 14:17:31 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsssm5usH3s8zTxbuvvLC5qdOmycy53MDt?= Message-ID: <201007281415.o6SEEsQn020097@mx1.redhat.com> utrace-devel??????????????? ?????2010?8?3-4? ?? ????: 2500?/ ?????????????????? ?????????????????????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ????? ??????????????? ???????????? ?????????????? ????????????? ????????????? ?????????? ??????????? ?????????????? ??????????? ---------------------------------------------------------------------------------------- ???? ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? -------------------------------------------------------------------------- ?????????? --- ?????????????1986????Gerber????????? Michigan State University (???????) ????????????,?????Heinz(??) ???????????????????????????????????????????? ????????????2000???,????????????????????????,?? ?????500?????????????,???????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????????????????? ?????????????,?????????,??,? ??????????,?????,???????????????????????????? ?????,??????????????,????????????????????? ?????????????????????????????????????? ??????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From resposta at emailmkt.cubospreto.com Wed Jul 28 14:36:15 2010 From: resposta at emailmkt.cubospreto.com (Fabiane Menezes) Date: Wed, 28 Jul 2010 14:36:15 GMT Subject: Tv via Internet 3000 Canais Message-ID: <201007281451.o6SEpFIY028656@mx1.redhat.com> An HTML attachment was scrubbed... URL: From resposta at emailmkt.cubopreto.com Wed Jul 28 14:36:47 2010 From: resposta at emailmkt.cubopreto.com (Adriana Ferraz) Date: Wed, 28 Jul 2010 14:36:47 GMT Subject: Como ganhar na Loteria Message-ID: <201007281451.o6SEpWgE006110@mx1.redhat.com> An HTML attachment was scrubbed... URL: From whitehallkcf at 21cn.com Wed Jul 28 15:49:25 2010 From: whitehallkcf at 21cn.com (whitehallkcf at 21cn.com) Date: Wed, 28 Jul 2010 23:49:25 +0800 (CST) Subject: =?UTF-8?Q?2674_=E4=BA=94=E6=AD=A5=E8=BF=9E=E8=B4=AF=EF=BC=81szqkdh813?= Message-ID: <18843232.419601280332165656.JavaMail.root@webmail5> An HTML attachment was scrubbed... URL: From vbwo at uykm.com Wed Jul 28 18:14:42 2010 From: vbwo at uykm.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Thu, 29 Jul 2010 02:14:42 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsz/rK28r9vt231s72tcS6w7e9t6g=?= Message-ID: <201007281814.o6SIEZA2003382@mx1.redhat.com> utrace-devel???????????? ?????2010?7?30-31? ?? ?????2010?9?3-4? ?? ?????2010?9?16-17? ?? ? ??2600?/???????????????????????????? ?????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------- ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ?????????????? ------------------------------------------------------------------------- ???? ????????????????????Office???Excel???????? ?????????BladeOffice??????????????????????????? ---------------------------------------------------------------------------------- ????: ???? ????????????????????????????????????????????????????... 1.????? 2.???????? 3.?????? 4.???????????????? 5.??????????? ?????? ?????????????????????????????????? ?????????????? ??????????????? 1.?????????? 2.?????? 3.???????? 4.?????? 5.?????? 6.??????????????????????? 7.?????????????? 8.???? ????????????? ????????????????????????????????????????????? 1.??????????? 2.????????? 3.????????? 4.????????? 5.????????? 6.????KPI?? ?????? ????????????????????????????????????? 1.????????? 2.???????? 3.???????? 4.??????? 5.?????? 6.??????? 7.?????? ???????? ????????????????????????????????????? 1.???? 2.??????????? 3.???? 4.??????????? 5.?????????? ???????????? ???????????????????????????????????????????????? 1.?????????? 2.????????????? 3.????????????????? 4.????????? 5.?????????? 6.??????????? 7.????????????? ??????????? ???????????????????????????????????????????????????????????? 1.??????? 2.??????? 3.??????1?1?????? 4.??????????? 5.?????????????? 6.????????RFM?? 7.?????(VOC)?? 8.??????????? 9.??????? ???????? ????????????????????????????????????????????????? 1.????????? 2.??????????? 3.???????????????? i. ???????????????? ii. ??????????? 4.??????????????????????????? i.????????????? ii.???????????? iii.?????????????????????? iv.????????????? 5.???????????????????????? -------------------------------------------------------------------------------------------- ?????????: ??????IPMA???????MCSE?MCDBA?????????????? ??????????????????????????????????????????OA? ERP?BI???????????????????????????????????????? ??????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????????? =============================================================================== ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Wed Jul 28 18:17:02 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Jul 2010 20:17:02 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100726142759.GA17171@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> Message-ID: <20100728181702.GA26678@redhat.com> On 07/26, Oleg Nesterov wrote: > > I decided to take a bit different approach, we will see if it > makes sense in the longer term. Please see the attached files, - ugdb.c The kernel module which implements the basic user-space API on top of utrace. Of course, this API should be discussed. - gdbstub The simple user-space gdbserver written in perl which works with ugdb API. Limitations: - this is just initial code, again. - doesn't work in all-stop mode (should be simple to implement). - currently it only supports attach, stop, cont, detach and exit. - the testing was very limited. I played with it about an hour and didn't find any problems, vut that is all. However, please note that this time the code is clearly opened for improvements. I stronly believe this is the only sane approach. Even for prototyping. No, _especially_ for prototyping! Btw, gdb crashes very often right after (gdb) set target-async on (gdb) set non-stop (gdb) file mt-program (gdb) target extended-remote :port (gdb) attach its_pid I didn't even try to investigate (this doesn't happen when it works with the real gdbserver). Just retry, gdb is buggy. What do you think? Oleg. -------------- next part -------------- #include #include #include #include #include #include #include struct ugdb_thread { int t_tid; int t_stop; int t_exit; struct pid *t_spid; struct ugdb *t_ugdb; struct utrace_engine *t_engine; struct list_head t_threads; struct list_head t_stopped; }; struct ugdb { spinlock_t u_llock; struct list_head u_threads; struct list_head u_stopped; wait_queue_head_t u_wait; }; // XXX: gdb is single-thread, no locking currently. #define T printk(KERN_INFO "TRACE: %s:%d\n", __FUNCTION__, __LINE__) static struct ugdb_thread *ugdb_create_thread(struct ugdb *ugdb, int tid) { struct pid *spid; struct ugdb_thread *thread; int err; err = -ESRCH; spid = find_get_pid(tid); if (!spid) goto err; err = -ENOMEM; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) goto free_pid; thread->t_tid = tid; thread->t_spid = spid; thread->t_ugdb = ugdb; INIT_LIST_HEAD(&thread->t_stopped); spin_lock(&ugdb->u_llock); list_add_tail(&thread->t_threads, &ugdb->u_threads); spin_unlock(&ugdb->u_llock); return thread; free_pid: put_pid(spid); err: return ERR_PTR(err); } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; spin_lock(&ugdb->u_llock); list_del(&thread->t_stopped); list_del(&thread->t_threads); spin_unlock(&ugdb->u_llock); put_pid(thread->t_spid); kfree(thread); } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread; spin_lock(&ugdb->u_llock); list_for_each_entry(thread, &ugdb->u_threads, t_threads) { if (thread->t_tid == tid) goto found; } thread = NULL; found: spin_unlock(&ugdb->u_llock); return thread; } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static struct ugdb_thread *ugdb_attach_thread(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread; void *errp; int err; thread = ugdb_create_thread(ugdb, tid); if (IS_ERR(thread)) { errp = thread; goto err; } thread->t_engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(thread->t_engine)) { errp = thread->t_engine; goto free_thread; } err = ugdb_set_events(thread, UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(DEATH)); if (err) { errp = ERR_PTR(-ESRCH); goto free_engine; } return thread; free_engine: ugdb_control(thread, UTRACE_DETACH); utrace_engine_put(thread->t_engine); free_thread: ugdb_destroy_thread(thread); err: return errp; } static void ugdb_detach_thread(struct ugdb_thread *thread) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); if (ret == -EINPROGRESS) utrace_barrier_pid(thread->t_spid, thread->t_engine); utrace_engine_put(thread->t_engine); ugdb_destroy_thread(thread); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; spin_lock_init(&ugdb->u_llock); INIT_LIST_HEAD(&ugdb->u_threads); INIT_LIST_HEAD(&ugdb->u_stopped); init_waitqueue_head(&ugdb->u_wait); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_thread *thread; while (!list_empty(&ugdb->u_threads)) { thread = list_first_entry(&ugdb->u_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread); } BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } // XXX: Of course, this all is racy -------------------------------------------- enum { STOP_RUN, STOP_REQ, STOP_ACK, STOP_FIN, }; static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; if (event == UTRACE_EVENT(DEATH)) { thread->t_exit = current->exit_code | INT_MIN; goto ack; } if (thread->t_stop == STOP_RUN) return UTRACE_RESUME; if (thread->t_stop != STOP_REQ) printk(KERN_INFO "XXX: %d, report_quiesce bad c_stop: %d\n", thread->t_tid, thread->t_stop); ack: thread->t_stop = STOP_ACK; // SIGKILL can re-add to stopped if (list_empty(&thread->t_stopped)) { spin_lock(&ugdb->u_llock); list_add_tail(&thread->t_stopped, &ugdb->u_stopped); spin_unlock(&ugdb->u_llock); } wake_up_all(&ugdb->u_wait); return UTRACE_STOP; } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { return UTRACE_RESUME; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_death = ugdb_report_death, }; static int ugdb_stop_thread(struct ugdb_thread *thread) { int err; if (thread->t_stop != STOP_RUN) return 0; thread->t_stop = STOP_REQ; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. temporarily. err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; if (thread->t_stop == STOP_RUN) return 0; if (!list_empty(&thread->t_stopped)) { spin_lock(&ugdb->u_llock); list_del_init(&thread->t_stopped); spin_unlock(&ugdb->u_llock); } thread->t_stop = STOP_RUN; ugdb_control(thread, UTRACE_RESUME); return 1; } static struct task_struct * ugdb_prepare_examine(struct ugdb_thread *thread, struct utrace_examiner *exam) { struct task_struct *task; if (!thread) return ERR_PTR(-ESRCH); task = pid_task(thread->t_spid, PIDTYPE_PID); if (!task) return ERR_PTR(-ESRCH); for (;;) { if (fatal_signal_pending(current)) return ERR_PTR(-EINTR); if (thread->t_stop == STOP_RUN) { printk(KERN_INFO "XXX: %d unexpected STOP_RUN\n", thread->t_tid); return ERR_PTR(-EBUSY); } if (thread->t_stop != STOP_REQ) { int err = utrace_prepare_examine(task, thread->t_engine, exam); if (err == 0) return task; if (err == -ESRCH) return ERR_PTR(err); } schedule_timeout_interruptible(1); } } // ----------------------------------------------------------------------------- #define UGDB_ATTACH (0x666 + 1) #define UGDB_DETACH (0x666 + 2) #define UGDB_STOP (0x666 + 3) #define UGDB_CONT (0x666 + 4) #define UGDB_GETEV (0x666 + 5) #define UGDB_PEEKMEM (0x666 + 6) #define UGDB_POKEMEM (0x666 + 7) static int ugdb_attach(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, tid); if (thread) return -EALREADY; thread = ugdb_attach_thread(ugdb, tid); if (IS_ERR(thread)) return PTR_ERR(thread); return 0; } static int ugdb_detach(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, tid); if (!thread) return -ESRCH; ugdb_detach_thread(thread); return 0; } static int ugdb_stop(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, tid); if (!thread) return -ESRCH; return ugdb_stop_thread(thread); } static int ugdb_cont(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, tid); if (!thread) return -ESRCH; return ugdb_cont_thread(thread); } enum { UGDB_EV_STOP, UGDB_EV_EXIT, }; struct ugdb_event { int ev_tid; int ev_type; union { unsigned ev_data; }; }; static int ugdb_getev(struct ugdb *ugdb, struct ugdb_event __user *uev) { struct ugdb_thread *thread; struct ugdb_event ev; if (list_empty(&ugdb->u_threads)) return -ECHILD; if (list_empty(&ugdb->u_stopped)) return -EWOULDBLOCK; spin_lock(&ugdb->u_llock); thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); list_del_init(&thread->t_stopped); spin_unlock(&ugdb->u_llock); ev.ev_tid = thread->t_tid; ev.ev_type = UGDB_EV_STOP; if (thread->t_exit) { ev.ev_type = UGDB_EV_EXIT; ev.ev_data = thread->t_exit & 0xffff; } if (copy_to_user(uev, &ev, sizeof(ev))) return -EFAULT; return 0; } struct ugdb_xmem { long tid; void __user *src, *dst; unsigned long len; }; static typeof(access_process_vm) *u_access_process_vm; static int ugdb_peekmem(struct ugdb *ugdb, struct ugdb_xmem __user *uxmem) { struct ugdb_xmem xmem; struct utrace_examiner exam; struct ugdb_thread *thread; struct task_struct *task; char mbuf[256]; int size; if (copy_from_user(&xmem, uxmem, sizeof(xmem))) return -EFAULT; thread = ugdb_find_thread(ugdb, xmem.tid); task = ugdb_prepare_examine(thread, &exam); if (IS_ERR(task)) return PTR_ERR(task); size = 0; while (xmem.len) { int chunk = min(xmem.len, sizeof (mbuf)); chunk = u_access_process_vm(task, (unsigned long)xmem.src, mbuf, chunk, 0); if (chunk <= 0) break; if (copy_to_user(xmem.dst, mbuf, chunk)) { size = -EFAULT; break; } xmem.src += chunk; xmem.dst += chunk; xmem.len -= chunk; size += chunk; } if (utrace_finish_examine(task, thread->t_engine, &exam)) size = -ESRCH; return size; } // XXX: temporarily hack !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define UGDB_GETREGS (0x666 + 100) #define REGSET_GENERAL 0 struct ugdb_getregs { long tid; void __user *addr; }; static int get_regset(struct task_struct *task, void __user *uaddr) { return copy_regset_to_user(task, task_user_regset_view(current), REGSET_GENERAL, 0, sizeof(struct user_regs_struct), uaddr); } static int ugdb_getregs(struct ugdb *ugdb, struct ugdb_getregs __user *uregs) { struct ugdb_getregs regs; struct utrace_examiner exam; struct ugdb_thread *thread; struct task_struct *task; int err; if (WARN_ON(sizeof(struct user_regs_struct) != 216)) return -EFAULT; if (copy_from_user(®s, uregs, sizeof(regs))) return -EFAULT; thread = ugdb_find_thread(ugdb, regs.tid); task = ugdb_prepare_examine(thread, &exam); if (IS_ERR(task)) return PTR_ERR(task); err = get_regset(task, regs.addr); if (utrace_finish_examine(task, thread->t_engine, &exam)) return -ESRCH; return err; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; int ret = -EINVAL; switch (cmd) { case UGDB_ATTACH: ret = ugdb_attach(ugdb, arg); break; case UGDB_DETACH: ret = ugdb_detach(ugdb, arg); break; case UGDB_STOP: ret = ugdb_stop(ugdb, arg); break; case UGDB_CONT: ret = ugdb_cont(ugdb, arg); break; case UGDB_GETEV: ret = ugdb_getev(ugdb, (void __user*)arg); break; case UGDB_PEEKMEM: ret = ugdb_peekmem(ugdb, (void __user*)arg); break; case UGDB_GETREGS: ret = ugdb_getregs(ugdb, (void __user*)arg); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = 0; if (!list_empty(&ugdb->u_stopped)) mask |= POLLIN; return mask; } // ----------------------------------------------------------------------------- static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); -------------- next part -------------- #!/usr/bin/perl -w #----------------------------------------------------------------------------- package utrace; use strict; use warnings FATAL => qw(all); use feature qw(switch); sub pr { main::pr(@_) } my $f_ugdb; use constant { # not really needed ECHILD => 10, EAGAIN => 11, UGDB_ATTACH => (0x666 + 1), UGDB_DETACH => (0x666 + 2), UGDB_STOP => (0x666 + 3), UGDB_CONT => (0x666 + 4), UGDB_GETEV => (0x666 + 5), UGDB_PEEKMEM => (0x666 + 6), UGDB_POKEMEM => (0x666 + 7), # XXX: temporarily hack !!!!! UGDB_GETREGS => (0x666 + 100), UGDB_EV_STOP => 0, UGDB_EV_EXIT => 1, }; sub create { sysopen $f_ugdb, '/proc/ugdb', 0 or return; return $f_ugdb; } sub attach_thread { my ($pid, $tid) = @_; defined ioctl $f_ugdb, UGDB_ATTACH, 0+$tid; } sub detach_thread { my ($tid) = @_; defined ioctl $f_ugdb, UGDB_DETACH, 0+$tid; } sub ck_true { defined (my $r = shift) or return; $r == 1 or pr "WARN! should be true"; 1; } sub stop_thread { my ($tid) = @_; ck_true ioctl $f_ugdb, UGDB_STOP, 0+$tid; } sub cont_thread { my ($tid) = @_; ck_true ioctl $f_ugdb, UGDB_CONT, 0+$tid; } sub get_event { defined ioctl $f_ugdb, UGDB_GETEV, my $event = 'x' x 64 or do { # just a sanity check return if $! == EAGAIN || $! == ECHILD; return (0, 'EV_ERROR', "[errno: $!]"); }; my ($tid, $type, $data) = unpack 'i!i!a*', $event; my @event; given ($type) { when (UGDB_EV_STOP) { @event = 'EV_STOP'; } when (UGDB_EV_EXIT) { @event = ('EV_EXIT', unpack 'I', $data); } @event = ('EV_UNKNOWN', $type); } $tid, @event; } sub read_mem { my ($tid, $addr, $size) = @_; my $mbuf = 'x' x $size; my $pbuf = unpack 'L!', pack 'P', $mbuf; my $xmem = pack 'L!4', 0+$tid, +$addr, 0+$pbuf, $size; my $r = ioctl $f_ugdb, UGDB_PEEKMEM, $xmem or return; substr $mbuf, 0, $r; } sub get_regs { my $tid = 0+shift; my $regs = 'x' x 216; # struct user_regs_struct my $pregs = unpack 'L!', pack 'P', $regs; my $xregs = pack 'L!2', 0+$tid, 0+$pregs; defined ioctl $f_ugdb, UGDB_GETREGS, $xregs or return; $regs; } #----------------------------------------------------------------------------- package main; use strict; use feature qw(state switch); use warnings FATAL => qw(all); no warnings 'portable'; #hex sub pr { print STDERR "@_\n" } =pod tread: T_PID T_TID pid, tid T_XID pPID.TID T_STP undef, false==pending, or STOP_REPLY process: P_PID pid P_TID list of sub-threads both: S_KEY = sorting key =cut #----------------------------------------------------------------------------- sub err { pr "ERR!! @_"; return; } sub hv($) { sprintf '%02x', 0+shift; } sub hs($) { unpack 'H*', shift // return undef; } sub shex($) { my $h = shift; ($h =~ s/^-//) ? -hex $h : +hex $h; } sub __s_key { sort { $a->{S_KEY} <=> $b->{S_KEY} } values %{+shift} } my ($O_NOACK, $O_NOSTOP); my ($S_KEY, $P_NUM, %P_ALL, %T_ALL) = (0, 0); my ($G_CURR, $C_CURR); sub select_threads { my ($pid, $tid) = @_; $pid < 0 || $tid < 0 and return err "unexpected multi-THREAD-ID" unless wantarray; return unless %T_ALL; if ($tid > 0) { my $t = $T_ALL{$tid} || return; $t->{T_PID} == $pid || return if $pid > 0; return $t; } my @p; if ($pid > 0) { @p = $P_ALL{$pid} || return; } else { @p = __s_key \%P_ALL; splice @p, 1 unless $pid; } my @t = map { my @t = __s_key $_->{P_TID} or die; splice @t, 1 unless $tid; @t; } @p; die unless @t; wantarray ? @t : $t[0]; } sub select_one_thread { scalar select_threads @_; } sub attach_thread { my ($p, $tid) = @_; my $pid = $p->{P_PID}; die if $T_ALL{$tid} || $p->{P_TID}{$tid}; utrace::attach_thread $pid, $tid or return err "attach $tid failed: $!"; $T_ALL{$tid} = $p->{P_TID}{$tid} = { S_KEY => ++$S_KEY, T_PID => $pid, T_TID => $tid, T_XID => sprintf('p%x.%x', $pid, $tid), T_STP => undef, }; } sub detach_thread { my ($p, $t) = @_; my $tid = $t->{T_TID}; utrace::detach_thread $tid, $t->{T_STP} or err "detach $tid: $!"; $_ && $_ == $t and undef $_ for $G_CURR, $C_CURR; $t == delete $T_ALL{$tid} or die; $t == delete $p->{P_TID}{$tid} or die; return $t; } sub detach_process { my $p = shift; detach_thread $p, $_ for values %{$p->{P_TID}}; $p == delete $P_ALL{$p->{P_PID}} or die; if (--$P_NUM <= 0) { die if $P_NUM; die if %T_ALL; die if %P_ALL; die if $G_CURR || $C_CURR; } die if keys %{$p->{P_TID}}; return $p; } sub proc_list_pid { my $pid = shift; my @tid = map /(\d+)\z/, glob "/proc/$pid/task/*"; # do not return an empty list! @tid ? @tid : $pid; } sub c_attach { # XXX: todo !!!!!! $O_NOSTOP || return err "Sorry, all-stop mode is not implemented yet."; my $pid = shex shift; $P_ALL{$pid} and return err "$pid already attached"; $P_NUM++; $P_ALL{$pid} = my $p = { S_KEY => ++$S_KEY, P_PID => $pid, }; for my $tid (proc_list_pid $pid) { attach_thread $p, $tid or do { detach_process $p; return; }; } # seems not strictly necessary ? $G_CURR = $p->{P_TID}{$pid} if !$O_NOSTOP; $p; } sub c_detach { detach_process $P_ALL{shex shift} || return; } # for ptrace plugin sub utrace::stop_pending { my $t = $T_ALL{+shift} || return; defined $t->{T_STP} && !$t->{T_STP}; } sub stop_one_thread { my $t = shift; unless (defined $t->{T_STP}) { utrace::stop_thread $t->{T_TID} or return err "stop $t->{T_TID}: $!"; $t->{T_STP} = ''; } $t; } sub stop_threads { stop_one_thread $_ for @{+shift}; } sub cont_one_thread { my $t = shift; if (defined $t->{T_STP}) { utrace::cont_thread $t->{T_TID}, $t->{T_STP} or return err "cont $t->{T_TID}: $!"; undef $t->{T_STP}; } $t; } sub cont_threads { cont_one_thread $_ for @{+shift}; } sub c_thread_info { 'm' . join ',', map $_->{T_XID}, select_threads -1, -1; } sub c_setcurr { my ($w, $pid, $tid) = @_; my $t = select_one_thread shex $pid, shex $tid or return; $w eq 'g' ? ($G_CURR = $t) : $w eq 'c' ? ($C_CURR = $t) : err "H$w not implemented"; } sub c_ck_alive { my ($pid, $tid) = @_; my $t = select_one_thread shex $pid, shex $tid or return; $t; } # include/gdb/signals.h:target_signal (incomplete) my @to_gdb_sigmap = ( (7, 10), (10,30), (12,31), (17,20), (18,19), (19,17), (20,18), (23,16), (29,23), (30,32), (31,12)); sub sig_to_gdb($) { my $sig = shift; state $map = {@to_gdb_sigmap}; $map->{$sig} || $sig; } sub sig_from_gdb($) { my $sig = shift; state $map = {reverse @to_gdb_sigmap}; $map->{$sig} || $sig; } # gdb-7.1/gdb/gdbserver/linux-x86-low.c my @x86_64_regmap = ( 10, 5, 11, 12, 13, 14, 4, 19, 9, 8, 7, 6, 3, 2, 1, 0, 16, 18, 17, 20, 23, 24, 25, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15); sub c_get_regs { my $regs = utrace::get_regs $G_CURR->{T_TID} or return undef; my @regs = unpack 'L!*', $regs; hs pack 'L!*', map { $_ >= 0 ? $regs[$_] // die : 0; } @x86_64_regmap; } sub c_read_mem { my ($addr, $size) = @_; hs utrace::read_mem $G_CURR->{T_TID}, hex $addr, hex $size; } my $RE_HEX = qr/([a-f\d]+)/; my $RE_PID = qr/(-?[a-f\d]+)/; my $RE_XID = qr/p$RE_PID.$RE_PID/; sub c_vcont { my %seen; for (split ';', shift) { my ($cmd, $pid, $tid) = /^ ([^:]+) (?: : $RE_XID )? \z/x or return err "vCont: can't parse '$_'"; ($pid, $tid) = defined $pid ? (shex $pid, shex $tid) : (-1, -1); my $handler; given ($cmd) { when ('t') { $handler = \&stop_threads } when ('c') { $handler = \&cont_threads } return err "vCont;$cmd is not implemented!"; } my @threads = grep !$seen{$_->{T_XID}}++, select_threads $pid, $tid or err "vCont: no threads in '$_'"; $handler->(\@threads); } scalar %seen; } # XXX: this all is wrong. blame gdb!!! sub hack_exit { my ($tid, $code) = @_; my $t = $T_ALL{$tid} || die; my $p = $P_ALL{$t->{T_PID}} or die; detach_thread $p, $t; return unless $p->{P_PID} == $tid; # main thread dies. report the group exit. detach_process $p; my $stp; if ($code & 0xff) { $stp = 'X' . hv sig_to_gdb($code & 0xff); } else { $stp = 'W' . hv(($code >> 8) & 0xff); } my $xid = hv $p->{P_PID}; $stp .= ";process:$xid"; return $stp; } my ($V_CUR, %V_STP, @V_STP); sub handle_event { my ($tid, $ev_name, @ev_data) = @_; my ($t, $stp); given ($ev_name) { when ('EV_STOP') { $stp = 'T00' } when ('EV_SIGNAL') { $stp = 'T' . hv sig_to_gdb $ev_data[0] } when ('EV_EXIT') { # XXX!!!!!! I do not know what to do with # the current limitations. The dirty hack # for now $stp = hack_exit $tid, $ev_data[0] or return; push @V_STP, +{ T_STP => $stp, }; return; } die "unimplemented event: tid=$tid $ev_name, @ev_data"; } $t = $T_ALL{$tid} || die; $t->{T_STP} = $stp . "thread:$t->{T_XID};"; push @V_STP, $t unless $V_STP{$t->{T_XID}}++; } sub get_notification { @V_STP && !$V_CUR && $V_STP[0]{T_STP}; } sub c_vstopped { @V_STP || err 'unexpected vStopped'; ++$V_CUR < @V_STP and return $V_STP[$V_CUR]{T_STP} || die; ($V_CUR, %V_STP, @V_STP) = (); return 'OK'; } sub handle_cmd { given ($_) { when (/^qSupported (.*multiprocess\+)?/x) { $1 || die "ERR!! need multiprocess\n"; @_ = join ';', qw{ PacketSize=400 QStartNoAckMode+ QNonStop+ multiprocess+}; } when ('vCont?') { @_ = 'vCont;t;c;C;s;S' } @_ = 'OK'; when ('QStartNoAckMode') { $O_NOACK = 1 } when (/^QNonStop:([01])/) { $O_NOSTOP = !!$1 } when ([qw'!']) {} @_ = undef; when (/^vAttach; $RE_PID \z/x) { @_ = $O_NOSTOP ? 'OK':'S05' if c_attach $1 } when (/^D; $RE_PID \z/x) { @_ = 'OK' if c_detach $1 } when (/^H (.) $RE_XID \z/x) { @_ = 'OK' if c_setcurr $1, $2, $3 } when ('qC') { @_ = 'QC' . $G_CURR->{T_XID} if $G_CURR } when (/^T $RE_XID \z/x) { @_ = 'OK' if c_ck_alive $1, $2 } when ('qfThreadInfo') { @_ = c_thread_info if %T_ALL } when ('qsThreadInfo') { @_ = 'l' } when (/^vCont;(.*)/) { @_ = 'OK' if c_vcont $1 } when ('vStopped') { @_ = c_vstopped } when ('g') { @_ = c_get_regs if $G_CURR } when (/^m $RE_HEX , $RE_HEX \z/x) { @_ = c_read_mem $1, $2 if $G_CURR } when (/^[GM]/) { } # uninplemented ... @_ = ''; when ('qTStatus') { @_ = 'T0' } when ('?') { @_ = $O_NOSTOP ? 'OK' : 'W00' } } return @_; } #----------------------------------------------------------------------------- my ($F_UGDB, $F_CONN, $F_OCMD); use constant { # ARCH DEPENDANT FIONBIO => 0x5421, EAGAIN => 11, }; sub echo { my $str = "@_"; substr($str, 62) = '...' if length $str > 64; pr $str; }; sub __put { # XXX: doesn't support NONBLOCK or short writes my $w = syswrite $F_OCMD, my $pkt = join '', @_; ($w ||= 0) == length $pkt or die 'ERR!! conn put(', length $pkt, ')', "failed: $w $!\n"; } sub __put_pkt { my $sym = shift; my $pkt = join '', @_; my $csm = 0; $csm += ord $1 while $pkt =~ /(.)/sg; __put $sym, $pkt, '#', hv $csm % 256; echo '<=', $pkt; } sub put_p { __put_pkt '$', @_; } sub put_n { __put_pkt '%', @_; } sub get_p { state $buf = ''; for (;;) { $buf =~ s/^\+*//; $buf =~ s/^\$ ([^#]*) \#..//x and $_ = $1, last; if ($buf =~ s/^([^\$]+)//s) { err "bad cmd or nack: $1"; } elsif (!sysread $F_CONN, $buf, 4096, length $buf) { return if $! == EAGAIN; pr 'conn closed:', $! || 'EOF'; exit; } } __put '+' unless $O_NOACK; echo '=>', $_; 1; } sub process_cmds { while (get_p) { my ($r, @r) = handle_cmd or next; put_p $r // 'E01', @r; } } sub process_ugdb { while (my @ev = utrace::get_event) { handle_event @ev; } my $n = get_notification; put_n 'Stop:' . $n if $n; } sub main_loop { ($F_CONN, $F_OCMD) = @_; $F_UGDB = utrace::create or die "ERR!! can't create utrace fd: $!\n"; ioctl $F_CONN, FIONBIO, pack 'i!', 1 or die $!; ioctl $F_UGDB, FIONBIO, pack 'i!', 1 or die $!; for (my $rfd = '';;) { vec($rfd, fileno $F_CONN, 1) = 1; vec($rfd, fileno $F_UGDB, 1) = 1; 0 < select $rfd, undef, undef, undef or next; # EINTR process_cmds if vec $rfd, fileno $F_CONN, 1; process_ugdb if vec $rfd, fileno $F_UGDB, 1; } } sub wait_for_connect { my $port = 0+shift; socket my $sk, 2,1,0 or return err "sock create: $!"; defined setsockopt $sk, 1,2,1 or return err "sock reuseaddr: $!"; bind $sk, pack 'Sna12', 2, $port, '' or return err "sock bind $port port: $!"; listen $sk, 2 or return err "sock listen: $!"; pr "wait for connection on $port port ..."; accept my $conn, $sk or return err "sock accept: $!"; return $conn; } sub main { my $port = 2000; if (@_) { $port = shift; die "Usage: $0 [port]\n" if @_ || $port =~ /\D/; } my $conn = wait_for_connect $port or exit; main_loop $conn, $conn; } main @ARGV; From bu at eyrh.com Wed Jul 28 19:58:23 2010 From: bu at eyrh.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 29 Jul 2010 03:58:23 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0NDV/rmk1/fNs7PvudzA7Q==?= Message-ID: <201007281958.o6SJwLO7023427@mx1.redhat.com> utrace-devel???????????????? ??????????2009??8??13-14?? ???? ??????????2009??8??21-22?? ???? ??????????2009??9??4-5?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ---------------------------------------------- ???????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????,???? ?????????????????????????????????????????????????????????????????????????? ??????????,???????????????????????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????? ???????????????????????????????? ----------------------------------------------- ???????? 1???????????????????????? 2???????????????????????????????????? 3?????????????????????????????????????????????? 4???????????????????????????? 5???????????????????????????????? 6?????????????????? --------------------------------------------- ???????? ?????????????????????????? 1???????????????????????????? 2???????????????????????????????? 3???????????????????????????????? 4???????????????????????? ?????????????????????????????? 1???????????????????????????? 2???????????????????????????????? 3???????????????????????????????? 4???????????????????????????? A???????????????? C???????????????????? D???????????????? E???????????????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????????????? ???????????????????????????? 1?????????????????????? 2???????????????????? 3?????????????????????????? 4???????????????????? ???????????????????????????????? 1???????????? 2?????????????????????????? 3?????????????????????????? 4???????????????????????? 5?????????????????? 6???????????????????????????????? 7???????????????? 8???????????????????? ???????????????????????????????????????? 1???????????? 2?????????????????? 3???????????? 4?????????????????????????????????????????????????? 5???????????????????????????????????????????? 6???????????????????????????????????? 7?????????????????????????????????? 8?????????????????????????????????????????? 9?????????????????? 10?????????????????? A???????????????????? B???????????? 11???????????????? A?????????????????? B?????????? 12?????????????? ?????????????????????????????????? 1?????????????????????? 2???????????????? 3???????????????????????? 4?????????????????????????? 5???????????????????? 6?????????????? 7???????????????????? 8???????????????????????????????? 9???????????????????? A???????????????????????????????????????????? B???????????????????????????? ???????????????????????? ?????????????????? 1?????????????????? 2?????????????? 3?????????????? 4?????????????? ?????????????????? 1???????????? 2?????????? 3?????????? ?????????????????????????? 1?????????? 2?????????????????????????????????? ???????????????????? ???????????????? ???????????????? ???????????????????? ???????????????????????????????????? 1?????????????????????? 2???????????????????????? 3???????????????????????????? 4???????????????????????? 5?????????????? 6?????????????? 7?????????????? 8?????????????? 9?????????? 10?????????? ???????????????????????????????? 1?????????? 2?????????? 3?????????????????? 4?????????????????????????????? 5?????????? 6?????????????? 7???????????????? 8???????????????? 9???????????????? ?????????????????????????????????? 1???????????????????????? 2???????????????????? 3???????????????????? 4?????????????????????? 5?????????????????????? 6?????????????????????? ------------------------------------------------- ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????? ?????????????????????????? ???????????????? ???????????????? ???????????????????? ???????????? ???????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From nd at xcb.com Wed Jul 28 20:15:27 2010 From: nd at xcb.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Wed, 28 Jul 2010 20:15:27 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsM0XQvdfKyei8xtPrudzA7by8x8k=?= Message-ID: <201007282015.o6SKExq1026705@mx1.redhat.com> utrace-devel?????-3E??????????? ?????2010?8?13-14? ?? ?????2010?8?28-29? ?? ? ??3800???????????????????????????????2000??3E??????1?) ?????????HR?????????????? HR???????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ====================================================================================== ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ??????????????????????????3E?????????????????500???? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ????????????3E????????????????????????????????????? ?????????????????????????????????????????????????3E ?????????????????????????????????????????????????? ????????????????????????????????????????????????? ================================================================================= ???? 1????????????????????? 2???3E?????????????? 3????????????????????? 4??????????3E????????? 5???????????????????? 6???????????3E???????????????????????????? 7???????????????????????????????????????????? ================================================================ ????? 1?1994?????????????????????????????????? 2?1997?????????????????????????????????? 3???????????????????????????????????? 4???????????????ChinaRen?????HR?????????????? 5????????????????????????HR?????????????????? 6??????????????????????????????????????????????????? ?????????????????????????? 7????3E???????????????????????3E???????????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????????????????? ?3E?????????????????????????????????????????????????? ????????????????3E?????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????????????????? ?????????????????????????????? ======================================================================================= ???? ???? ???? ??????????????????? ?????????????????????? ????????????????????????? ??????????????????????? ?????????????? ????????????????? ???? 3E?????? ???????????????? ???3E?3E?????????????? ?????????????????? ??????????????????? ???????????????????????? ???? ?????????? ?????????? ??????????????? ???????????????? ?????????????????? ????point-factor????????? ?????30??????? ???????????? ???????????????????? ?????????????????Grading Matrix? ?????????????????? ????????????????? ???????????????????????? ????????????? ???? ???????? a??????? ???????????????????? ??????????????? ???????????????????????????????? ??????????????????????????? ???????????????????????? ??????????????????????? ?????????????????????????? b??????? ???????????????????????? ?????????????????????? ??????????????????????? ????????????????? ?????????????????????????????????? ?????????????????? ???????????????? c??????? ??????????????????????????????????????????????????? ??????????????????????????? ????????3P???????????????3E??????????????? ????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????? ??????? ??????????? ???? ???? a??? ???????????????????? ???????????????? ?????????????????? ?????????? ?????????????????????? ???????????????????????? ???????????????????? b??? ?????????????????????????????? ???????????????????????? ???????????????????????????????CR???????? ????CR??????? ???????????????????????????????? ????????? ???????????????????????????????????????? ??????????????? ?????????????????????????????????????? ?????????????? C????????? ?????????????????????? ???????? ?????????????????????????? ????????????3E??????????????????????????????? ?????????????????? ???? ???????? ?????skill-based???????????? ????????????????????????? ???? ???? ????????????????????????????????????? ------------------------------------------------------------------------------- ?3E?????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From wkbnpanseuc41 at 21cn.com Thu Jul 29 13:36:05 2010 From: wkbnpanseuc41 at 21cn.com (wkbnpanseuc41 at 21cn.com) Date: Thu, 29 Jul 2010 21:36:05 +0800 (CST) Subject: =?UTF-8?Q?2237_=E6=82=A8=E5=A5=BD=EF=BC=81uirgul933?= Message-ID: <26804450.511421280410565886.JavaMail.root@webmail3> An HTML attachment was scrubbed... URL: From boughed at amstaff.hu Thu Jul 29 14:33:39 2010 From: boughed at amstaff.hu (Fleisner Archdale) Date: Thu, 29 Jul 2010 11:33:39 -0300 Subject: set at liberty a large amount of carbon, whi Message-ID: <4C518FAC$8777276@amstaff.hu> A non-text attachment was scrubbed... Name: northbound.png Type: image/png Size: 20478 bytes Desc: not available URL: From fche at redhat.com Thu Jul 29 21:38:03 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 29 Jul 2010 17:38:03 -0400 Subject: gdbstub initial code, another approach In-Reply-To: <20100728181702.GA26678@redhat.com> (Oleg Nesterov's message of "Wed, 28 Jul 2010 20:17:02 +0200") References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> Message-ID: Oleg Nesterov writes: > [...] > - ugdb.c > > The kernel module which implements the basic > user-space API on top of utrace. Of course, > this API should be discussed. > - gdbstub > > The simple user-space gdbserver written in > perl which works with ugdb API. > [...] To the extent that the problems with an in-kernel gdbstub are weaknesses in the protocol - or gdb's implementation thereof - how would this split improve that situation? - FChE From cgvb at eht.com Fri Jul 30 03:09:07 2010 From: cgvb at eht.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Fri, 30 Jul 2010 03:09:07 -0000 Subject: =?GB2312?B?QjZ1dHJhY2UtZGV2ZWzXqNK1w9jK6by8xNzM4cn9?= Message-ID: <201007300308.o6U38hns002220@mx1.redhat.com> utrace-devel???????????????????????????????? ??????2010??7??31??-8??1?? ?????????? ????: 2010??8??7-8?? ?????????? ??????2010??8??14-15?? ?????????? ??????????2500/???????????????????????????????????? ?????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ????????????????????????????chinammc2010 at 126.com?????? ======================================================================================== ???????????????????? 1.?????????????????????????????????????????????????????????????????????? 2.???????????????????????????????????????? 3.???????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? 5.?????????????????????????????????????????????? 6.?????????????????????????? 7.?????????????????????????????????????????? 8.???????????????????????????????????????????????????????? 9.???????????????????????????????????????????? 10.???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? =========================================================================================== ????????: ???????? ????/?????????????? 1.????/???????? 2.????????/???????????????? 3.????????/?????????????????????????? 4.????????/???????????????????????? 5.???????????????????????D?D?????????????????? 6.???????????????????????????? 7.?????????????????????????????????????????? 8.????/?????????????????? 9.???????????????????????????????????????????? ???????? ????????/?????????????? 1.????/?????????????????D?D????????????????/????/???????? 2.?????????????????????? 3.?????????????????????????????????????????????????? 4.????????????????????PDP??????NLP???? 5.????????????????????????????5W1H?????????? 6.?????????????????????????? 7.???????????????? 8.???????????????????????????????????????????????????????????????? ???????? ????????5S???? 1.5S?????? 2.???????????????????????? 3.???????????????????????? 4.???????????????????????? 5.???????????????????????? 6.???????????????????????????? ???????????????? 1.??????????5?????? 2.???????????????????????????? 3.?????????????????? 4.???????????????????????????????? 5.???????????????????????????????????????????????????????? 6.?????????????????????????????????????????????? 7.?????????????????????????? ?????????????????????????? 1.???????????????????????????? 2.PDCA?????????????????????????? 3.????SMAC???????????????????? 4.??????????/????/?????????????????????? 5.???????????????????????????????????????????????????????? ?????????????????????????????????? 1.?????????????? 2.?????????????? 3.?????????????????????????????????? 4.?????????????????? 5.????????????????????12?????? 6.?????????????????? 7.???????? 8.???????????????????????????????? ???????????????? 1.???????????????? 2.?????????????????? 3.?????????????????? 4.?????????????????? 5.?????????????????? 6.?????????????????? 7.?????????????????? ?????????????????????????????? 1.???????? 2.?????????? 3.?????????????????? ???????????????????? 1.?????????????????????????????? 2.?????????????? ???????????????????????????????????????????????????????????????? ??????????????????????????????/????/?????????????????????????????????????? 3.?????????????????????????????? ?????????????????????????????????????????????? ========================================================================================== ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????5????????????500?????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????TTT???????????????? ??????????????????????????/???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????TCL?? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? =========================================================================================== ??????????/????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From oleg at redhat.com Fri Jul 30 12:57:55 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Jul 2010 14:57:55 +0200 Subject: gdbstub initial code, another approach In-Reply-To: References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> Message-ID: <20100730125755.GA6438@redhat.com> On 07/29, Frank Ch. Eigler wrote: > > Oleg Nesterov writes: > > > [...] > > - ugdb.c > > > > The kernel module which implements the basic > > user-space API on top of utrace. Of course, > > this API should be discussed. > > - gdbstub > > > > The simple user-space gdbserver written in > > perl which works with ugdb API. > > [...] > > To the extent that the problems with an in-kernel gdbstub are > weaknesses in the protocol - or gdb's implementation thereof - how > would this split improve that situation? I have the strong desire to ask you by turn why do you think that in-kernel gdbstub can help in any way ;) Yes, I never liked the idea of in-kernel gdbstub. Apart from too-highlevel and vague it is also a bit limited. And some things, say, register renumbering, doesn't belong to kernel. Or vRun. Many other things. The only advantage is that we already have the great tool which works with this protocol - gdb. Ok, it is easy to criticize, and my opinion doesn't really matter. We can put it in kernel later, when we have something more than just the proof of concept. But I do not see how in-kernel gdbstub can help even to prototype things. In my opinion it only complicates this. If nothing else, it is not easy to test even the simple things. Just imagine the simple tests like ptrace-tests rewritten to work via remote protocol. IIUK, the main goal is prototype the new generic API, while the remote protocol (in my opinion) is obviously can't be considered as such. With this split it is possible to try to add some API and test it with or without gdb. Also, it is much more easy to play with the the protocol extensions (which I believe it needs) this way. It would be (I think) much easier to teach the real gdbserver and/or gdb to use this new API if we already had the userspace aplication which actually works using this API. OTOH, with this split we still have the same advantage: we can use gdb to prove that this code can do something useful. Oleg. From fche at redhat.com Fri Jul 30 13:16:27 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Fri, 30 Jul 2010 09:16:27 -0400 Subject: gdbstub initial code, another approach In-Reply-To: <20100730125755.GA6438@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> Message-ID: <20100730131627.GA2793@redhat.com> Hi, Oleg - > [...] > But I do not see how in-kernel gdbstub can help even to prototype > things. In my opinion it only complicates this. If nothing else, > it is not easy to test even the simple things. Just imagine the > simple tests like ptrace-tests rewritten to work via remote > protocol. (One could use a new user-space library. There is not that much complexity difference between a write/read syscall pair and a complex ioctl.) > IIUK, the main goal is prototype the new generic API [...] It would > be (I think) much easier to teach the real gdbserver and/or gdb to > use this new API if we already had the userspace aplication which > actually works using this API. To an extent, it's all a SMOP. But the key is the level of abstraction provided by any new API. ptrace(2) is low, the gdb-wire-protocol is high, and both are pretty well established. A brand new API aiming into some new middle point will be harder to validate. > OTOH, with this split we still have the same advantage: we can > use gdb to prove that this code can do something useful. Not if you run into the exact same multithreading protocol glitches, but this time with three separate interacting bodies of code instead of two. - FChE From jan.kratochvil at redhat.com Fri Jul 30 13:25:37 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 30 Jul 2010 15:25:37 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100730125755.GA6438@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> Message-ID: <20100730132537.GA15448@host1.dyn.jankratochvil.net> On Fri, 30 Jul 2010 14:57:55 +0200, Oleg Nesterov wrote: > IIUK, the main goal is prototype the new generic API, As I thought there is an agreement the ptrace API has to stay. ptrace as an API is really ugly but it works. GDB internally already has an abstraction on top of it (linux-nat.c as a target). We definitely need some serialized protocol as we need remote debugging with multiple inferiors for cloud. The gdb remote protocol is already very thin to just provide some "ptrace-like" functionality serialized over the wire. I already tried (test only, not indended for a production) once to "replace ptrace" with disagreement on the design: Re: Proof-of-concept on fd-connected linux-nat.c server http://sourceware.org/ml/archer/2009-q2/msg00082.html I do not see why to create a new layer (your `new generic API') between kernel and gdbserver-in-userland. > while the remote protocol (in my opinion) is obviously can't be considered > as such. With this split it is possible to try to add some API and test it > with or without gdb. Also, it is much more easy to play with the the > protocol extensions (which I believe it needs) this way. If it is only a development tool for the in-kernel server then OK. > It would be (I think) much easier to teach the real > gdbserver and/or gdb to use this new API gdb linux-nat.c (=local gdb) should be deprecated. There is definitely a need for remote target and actively maintaining two modes is not effective, we can run gdbserver even during single-host debugging. We can port gdbserver to anything but I do not see the point. We should probably move the threading support from gdbserver to gdb but there isn't much left to do in userland gdbserver with properly designed kernel API. Thanks, Jan From oleg at redhat.com Fri Jul 30 14:41:24 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Jul 2010 16:41:24 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100730132537.GA15448@host1.dyn.jankratochvil.net> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730132537.GA15448@host1.dyn.jankratochvil.net> Message-ID: <20100730144124.GA10396@redhat.com> On 07/30, Jan Kratochvil wrote: > > On Fri, 30 Jul 2010 14:57:55 +0200, Oleg Nesterov wrote: > > IIUK, the main goal is prototype the new generic API, > > As I thought there is an agreement the ptrace API has to stay. Of course, ptrace can't go away. > We definitely need some serialized protocol as we need remote debugging with > multiple inferiors for cloud. Nobody argues. > I do not see why to create a new layer (your `new generic API') between kernel > and gdbserver-in-userland. Because gdb is not alone? I agree, it is probably most important. > > while the remote protocol (in my opinion) is obviously can't be considered > > as such. With this split it is possible to try to add some API and test it > > with or without gdb. Also, it is much more easy to play with the the > > protocol extensions (which I believe it needs) this way. > > If it is only a development tool for the in-kernel server then OK. Right now I do not know. > > It would be (I think) much easier to teach the real > > gdbserver and/or gdb to use this new API > > gdb linux-nat.c (=local gdb) should be deprecated. There is definitely a need > for remote target and actively maintaining two modes is not effective, we can > run gdbserver even during single-host debugging. OK, > We can port gdbserver to anything but I do not see the point. We should > probably move the threading support from gdbserver to gdb but there isn't much > left to do in userland gdbserver with properly designed kernel API. IOW, you think that it is better to shift gdbserver into kernel-space than port the existing one to the new API or write the new one in user space ? Oleg. From oleg at redhat.com Fri Jul 30 14:58:51 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Jul 2010 16:58:51 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100730131627.GA2793@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730131627.GA2793@redhat.com> Message-ID: <20100730145851.GB10396@redhat.com> On 07/30, Frank Ch. Eigler wrote: > > Hi, Oleg - > > > > [...] > > But I do not see how in-kernel gdbstub can help even to prototype > > things. In my opinion it only complicates this. If nothing else, > > it is not easy to test even the simple things. Just imagine the > > simple tests like ptrace-tests rewritten to work via remote > > protocol. > > (One could use a new user-space library. There is not that much > complexity difference between a write/read syscall pair and a complex > ioctl.) Oh. I do not think so. First af all, I do not know what this library can actually do, except it can provide the helpers for get/put packet plus some parsing. But in any case, we don't have this lib right now. And write/read pair is not only inconvenient. Imho, it is really bad because read() is used for the asynchronous events as well. > > IIUK, the main goal is prototype the new generic API [...] It would > > be (I think) much easier to teach the real gdbserver and/or gdb to > > use this new API if we already had the userspace aplication which > > actually works using this API. > > To an extent, it's all a SMOP. But the key is the level of > abstraction provided by any new API. ptrace(2) is low, the > gdb-wire-protocol is high, and both are pretty well established. A > brand new API aiming into some new middle point will be harder to > validate. Yes, agreed. But I hope that the user-space gdbserver which actually works on top of this API can be considered as validation. IOW, if this API is simple and good enough to write the reasonable gdbserver, then it probably makes sense. > > OTOH, with this split we still have the same advantage: we can > > use gdb to prove that this code can do something useful. > > Not if you run into the exact same multithreading protocol glitches, > but this time with three separate interacting bodies of code instead > of two. I don't understand this part. We already have some problems here, with the existing protocol, yes. If we want to fix them, I do not understand how the fact that some code runs in user-space can't complicate things. Oleg. From jan.kratochvil at redhat.com Fri Jul 30 15:20:25 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 30 Jul 2010 17:20:25 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100730144124.GA10396@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730132537.GA15448@host1.dyn.jankratochvil.net> <20100730144124.GA10396@redhat.com> Message-ID: <20100730152025.GA22951@host1.dyn.jankratochvil.net> On Fri, 30 Jul 2010 16:41:24 +0200, Oleg Nesterov wrote: > IOW, you think that it is better to shift gdbserver into kernel-space than > port the existing one to the new API or write the new one in user space ? So far I just assumed kernel-space ugdb is the plan. As I wrote before I do not know gdbserver too much. If you check gdb/gdbserver/linux-low.c it is just one big ptrace/wait/\/proc interface. I would guess it could be more simple with the utrace API at hand. Catching up with systemtap's 200x higher software-watchpoint performance over current (local) gdb (described in "[debug-list] Utrace Discussion Notes" off this list) could be easier with in-kernel gdb I thought. Thanks, Jan From tromey at redhat.com Fri Jul 30 17:59:08 2010 From: tromey at redhat.com (Tom Tromey) Date: Fri, 30 Jul 2010 11:59:08 -0600 Subject: gdbstub initial code, another approach In-Reply-To: <20100730132537.GA15448@host1.dyn.jankratochvil.net> (Jan Kratochvil's message of "Fri, 30 Jul 2010 15:25:37 +0200") References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730132537.GA15448@host1.dyn.jankratochvil.net> Message-ID: >>>>> "Jan" == Jan Kratochvil writes: Jan> gdb linux-nat.c (=local gdb) should be deprecated. There is Jan> definitely a need for remote target and actively maintaining two Jan> modes is not effective, we can run gdbserver even during Jan> single-host debugging. I think we should differentiate a bit between Oleg's project and projects internal to gdb. I agree that the current approach of writing all linux-nat code twice -- once for gdb and once for gdbserver -- is no good. Also, I think Oleg's recent questions and investigations have shown that perhaps gdbserver is currently a bit lacking for local debugging. But, a lot of this is a problem specific to gdb. We could, for example, remove linux-nat.c and move to only allowing gdbserver. Or, we could have gdb and gdbserver share code. But either of these would be independent of whatever interface the kernel provides. Tom From kaishifa66 at 21cn.net Sat Jul 31 02:15:47 2010 From: kaishifa66 at 21cn.net (kaishifa66 at 21cn.net) Date: Sat, 31 Jul 2010 10:15:47 +0800 (CST) Subject: =?UTF-8?B?5ryG6buR5Lit5ZKx5Lus55qE56ys5LiA5qyhMjA2?= Message-ID: <2035505.20381280542547186.JavaMail.root@pay1> An HTML attachment was scrubbed... URL: From nasim.abb14 at bol.com.br Sat Jul 31 06:56:55 2010 From: nasim.abb14 at bol.com.br (nasim.abb14) Date: Sat, 31 Jul 2010 03:56:55 -0300 Subject: Assalamn aleikum Message-ID: <4c53c93763f4_67693f7e70274@winter22.tmail> An HTML attachment was scrubbed... URL: From mrsmargaret_brown at w.cn Sat Jul 31 12:34:11 2010 From: mrsmargaret_brown at w.cn (Mrs.Margaret Brown) Date: Sat, 31 Jul 2010 12:34:11 +0000 (GMT) Subject: (Dear God's elect,) Message-ID: <497870.66160.qm@web87002.mail.ird.yahoo.com> (Dear God's elect,) I am touched by God to hand you over this money considering my last wish, and you should also know that my contact to you is by special grace of God, please understand that you are not helping me rather you are working for God the creator of heaven and earth. In respect of my previous message; Nevertheless, (30% Percent) of the total money 8,500,000.00 USD is for your personal use and 70 Percent to help orphanages, Building a Clinic school and widows to endeavor that the house of God is maintained, I hope you will utilize this money the way I instructed you herein. On the process of receiving your first response, i have now extented the communication to the knowledge of my personal lawyer who will take a proper charge of the fund remiting procedure to your destination to enable you excute my last wished project. The contact of the attoney in charge will be made available to you as soon as i am convinced of your honesty in this project for the release of the amount. With regard to my ill health and the presence of my husband's relatives around me here in the hospital, I do not need any telephone communication in this mostly because I seldom them to know about this as they are not aware of the deposited money. Moreover, further discusion in this matter will require your official presence to change the related documents to your name due to my illness of course will not allow me to move out of this hospital bed, meanwhile the bank will also request your present to sign the release order document considering the amount of money involve (8,500,000.00 USD) On this reason you will make arrangement to undertake (Three to Four 3/4) working days in order to meet with my lawyer to enable him make sure that you are properly handed over the fund to go on with processing of my project. Don't forget to always pray for me because all my hope to survive is in God the creator who holds death and life. Hoping to receive your reply. Mrs.Margaret Brown -------------- next part -------------- An HTML attachment was scrubbed... URL: From parkway at irissi.es Sat Jul 31 18:58:48 2010 From: parkway at irissi.es (Balerio Pfohl) Date: Sat, 31 Jul 2010 20:58:48 +0200 Subject: if the paper is stiff, Message-ID: <0f7a175c68fb20100731164603@irissi.es> A non-text attachment was scrubbed... Name: satirically.png Type: image/png Size: 21614 bytes Desc: not available URL: From news at maisservicos.com Sat Jul 31 21:12:50 2010 From: news at maisservicos.com (MaisServicos) Date: Sat, 31 Jul 2010 22:12:50 +0100 Subject: Junte-se aos 100.000 que poupam no seguro automovel Message-ID: <20100731211314.023421DC2FE@server7.nortenet.pt> Se n??o conseguir visualizar este email, clique aqui. 100.000 clientes j?? poupam no Seguro Autom??vel com a LOGO! A LOGO oferece-lhe agora 75 dias de Seguro GR?TIS para que se possa juntar aos 100.000 clientes que j? poupam no seu Seguro Autom?vel. Aproveite j? esta oferta especial at? 31 de Julho! Se n?o desejar receber mais esta newsletter, responda a este email com "REMOVER" no assunto. N?o dispensa a consulta da informa??o pr?-contratual e contratual legalmente exigida. Condi??es da campanha em logo.pt. Seguros LOGO, SA. NOTA INFORMATIVA: O presente email destina-se ??nica e exclusivamente a informar potenciais utilizadores e n??o pode ser considerado SPAM. De acordo com a legisla????o internacional que regulamenta o correio electr??nico, "o email n??o pode ser?? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Para deixar de receber estas ofertas no seu e-mail clicar aqui -------------- next part -------------- An HTML attachment was scrubbed... URL: From bob at ns1.sosam.gov.tr Sat Jul 31 20:54:12 2010 From: bob at ns1.sosam.gov.tr (Stark E Constance) Date: Sat, 31 Jul 2010 23:54:12 +0300 (EEST) Subject: Healthcare/Business and Finance/Consumer/Professional Lists Message-ID: <20100731205412.7D2E692237@arti.ankara.netsec.tr> Until Friday Jul 30 you can buy any list below for just $175 each, 3 for $299 or 5 for $399: All lists are 100% optin and are 6 months or newer. ** HEALTHCARE LISTS ** - Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers - Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers - Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers - Dentists - 164k records, 45k emails, 77k fax numbers - Veterinarians - 78,986 total records with 1,438?emails and 1,050?fax numbers - Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) - National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics - Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) - Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees - Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers - Oncology Doctors - 2,200 records all with emails - US Surgery Centers - 85k records and 14k emails - Massage Therapists - 76,701 records and 8,305 emails - Acupuncturists - 23,988 records 1,826 emails - Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers - Mental Health Counselors - 283,184 records 7,206 emails - Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers - Optometrists - 63,837 records 2,015 emails - Psychologists - 272,188 records and 9,874 emails ** BUSINESS AND FINANCE LISTS ** - Hotels - 34,815 total records * 1,642 emails - Real Estate Agents - 1 million records with emails - American Business Email List - 2 million emails various businesses - US New Business Database - 4.8 million records all with emails - Manufacturers Database - 1,057,119 records with 476,509 emails - Financial Planners Database - 148,857 records all with emails - Finance and Money Professionals Database - 116,568 records all with emails ** CONSUMER LISTS ** - American Consumer Database - 300,000 records all with emails. - Credit Inquiries Database - 1 million Full Data Records all with emails - American Homeowners - 1 million Full Data Records all with emails ** PROFESSIONALS LISTS ** - USA Lawyers Database - 269,787 records with 235,244 emails - Police and Sheriff Services - 42,987 records and 114 emails - Criminal Attorneys - 142,906 total records, 99,857 emails email me if you're interested: dataexperts at gmx.com to adjust your subscription status email to offthelist at gmx.com From pbt at baev.com Sun Aug 1 06:43:11 2010 From: pbt at baev.com (=?GB2312?B?x+vT0LnYyMvKwg==?=) Date: Sun, 1 Aug 2010 14:43:11 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyfqy+s/Ws6HOo7v61KS3wNPrv9jWxg==?= Message-ID: <201008010643.o716h6N3000978@mx1.redhat.com> utrace-devel????????????? ?????2010?8?26-27? ?? ?????2010?8?28-29? ?? ????: ???????????????????????????????? ????: ?????????? ???2,600?/? ??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? --------------------------------------------------------------- ??????: ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????????????????????? ??????: ????????????????????????????????????? ??????????????????????????????????????? ????????????????????????????????????? ============================================================================= ??????: ???????????????? ????????? ??????????????? ???????????? ???????????? ??????????? ???????????? ??????????1/3??3? ????????? ????????????????? ??????????????? ???????????????? ??????????? ???????????? ??????????????? ????????60000?? ????????????? ????????????? ????????????? ?????5S?????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S---? ?5S?????????????? ?5S?????????????? ????????????? ????????? ??????????????? ???????????????????? ???????????? ???????? ??????????????????? ??????????? ???????????????? ????????? ???100%??????????? 100%?????????? ???????????????????? ??????????????? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ??????????????????? ????????????? ??????????????? ????????????????????? ??????????????????? ???????????????????? ??????????????? ?????????????? ???????????????? ??????????????? ?????????????? ?????????????? ????????????? ??????????????? ??????????????? ???????+????????+??? ??????????????????? ============================================================================= ?????????? ??????? ????????? ?MMC?????????? ???????????????(SUMIDA)????????(CASIO)???13?? ??????????????????????????????????????? ?????? ??WF&IE???????????????????????????? ???????????????????????????JIT??????NPS??? ?????????? ??????????????(??,??,??,??,???? ?)??????:??????????ST???????????????????? ??????????????????????????????????????? ??????????????????80?????? ????????????????????????????????????? ????????ABB???????????????-?????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? ??????????????????,?????????????????? ??????????????????????????????????????? ??????? ============================================================================= ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From wollenoxoyj at 21cn.com Sun Aug 1 11:32:35 2010 From: wollenoxoyj at 21cn.com (wollenoxoyj at 21cn.com) Date: Sun, 1 Aug 2010 19:32:35 +0800 (CST) Subject: =?UTF-8?Q?4247_=E6=82=A8=E5=A5=BD=EF=BC=81agtcfq743?= Message-ID: <27234044.404351280662358016.JavaMail.root@webmail5> An HTML attachment was scrubbed... URL: From gfhd at shade.com Sun Aug 1 11:45:20 2010 From: gfhd at shade.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sun, 01 Aug 2010 11:45:20 -0000 Subject: =?GB2312?B?RDh1dHJhY2UtZGV2ZWyyv8PF1ve53LncwO3E3MGmzOHJ/Q==?= Message-ID: <201008011145.o71Biwix011660@mx1.redhat.com> utrace-devel???????????? ?????2010?8?12-13? ?? ?????2010?8?14-15? ?? ?????2010?8?28-29? ?? ?????2200 /?????????????????? ?????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ====================================================================================== ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ??????? ======================================================================================= ???? ??????????????????? ??????????????????????? ????????? ????????????? ??????????????????? ????????????????? ======================================================================================= ???? ???? ?????? ???????????? 1. ???????????? 2. ???????? 3. ???????? 5. ??????????? ?????????? 1. ??????? 2. ?????????? 3. ????????? 4. ????????????? ?????????? ???? ???? ??????????? 1. ?????????? 2. ????SMART?? 3. ?????????? ??????????-??????? ??????????????? 1.?????? 2.?????8??? 3.?????? 4.?????????? 5.??????????????? ??????????????????? ??????????? 1.?????????????????? 2???????????XY?? 2??????????? 2?????????????? 2.??????7???????? 2???? -- ????? 2???? - ????? 2???? - ????? 2???? - ????? 2???? -- ????? 2???? - ????? 2???? - ????? ?????????? ????????????? 1.???????? 2??????????????? 2????????? 2?????????? 2???????? 2??????PDCA???? 2?????????? 2????????????????? 2.???????? 2????? 2????? 2????? 2????? 2????? 2????? 2????? ???? ???? ?????????? 1.???????????????? 2.??????????????????????? 3.???????-?????????????? 4.???? 2?????????????? 2???????????? 2??? 2?????????? 2?????????? 2???????????? 2?????????????? 5.???? 2?????????????? 2???????????? 6.???? 2?????????????? 2???????????? 2???????????????? 2????????????? 7.???? 2??????????????????????????????? 2????????????????????????????? 2????????????????? 2????????????????? 2????????????? ????????? 1.??????? 2?????? --????????????????????????? 2????????????? 2???????????? 2???????????? 2????????????????????? 2.???? 2????????? 2???????????? 2???????????? 2??????????? 2?????????? 2??????????? 2??????????? 2??? 2????????? 2???????? 2??????????????? 3.???? 2???????????????????? 2???????????????? 2??????????????? 2??????????????? 2?????8??? 2????????????? -- ??????12?? ?????? 1.??????????????????? 2.?????????? 3.???????????? 4.????? 5.???????? 6.?????????? 7.?????????? 8.??????? 9.????????? ?? ???????? 1.???????? 2.???7??????? 3.???????? 4.??????????????? 5.???????????? 6.??????????????? 7.?????????? ======================================================================================== ?????????Michael?,????MBA,????PMP????PMP??????, ???????????????????20????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ??????????????????????????? ??????????????????????????????????????? ????????????????????? ------------------------------------------------------------------------------- ???????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From zschu at nkol.com Mon Aug 2 01:24:34 2010 From: zschu at nkol.com (=?GB2312?B?xeDRtQ==?=) Date: Mon, 2 Aug 2010 09:24:34 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVszeLP+s3FttO9qMno0+u8pMD4?= Message-ID: <201008020124.o721OU8G002136@mx1.redhat.com> utrace-devel???????????????????? ?????2010?8?13-14? ?? ?????2010?8?20-21? ?? ?????2010?8?28-29? ?? ? ??2500?/????????????????? ???????????????????????????????????? ??????????????????SOHO?? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ??????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? ????????????????????????????????????? 1??????????????????????????? 2???????????????????????????????? 3?????????????????? 4???????????????? 5??????????????????????? 6????????????????????? 7??????????????????????????????????????????????? 8????????????????????? 9??????????????????????????????? 10???????????????????????????? 11???????????????????????????? 12?????????????????? 13?????????????????????????????????? 14???????????????????????????????????? 15?????????????????????? 16??????????????????? 17?????????????????????????????????????????? 18???????????? 19???????????????????????? 20????????????? ----------------------------------------------------------------------------- ????: ??? ???????????????? ???????????????? ???????????????? ???????????? ????????????????????????? ??????????????? ??????????????? ????????????????? ??? ?????????????? ??????????? ??????????? ?????????????????? ?????????????????? ??????????? ???????????????????? ?????????????????? ??????????? ??? ??????????? ?????? ?????? ?????? ?????? ?????? ??????????? ??????????? ??????????? ???????????? ??????????? ?????????? ??? ?????????????????? ???????????????? ???????????? ???????????????? ??????????????? ??????????? ?????????????? ???????????? ?????????? ??? ??????????? ???????????? ???????????? ??????????????? ?????????????????? ?????????????? ???????????? ????????????? ??? ?????????????? ???????? 1??? 2??? 3??? 4?????? 5??????? 6??????????????? ?????????????? 1???? 2???????????? 3???????????? 4?????? 5?????????? 6???????? 7???????? ????????? ?????????????? ????????? 1????? 2?????? 3?????? 4??????? 5????????????????? 6????????????????? 7?????????? 8?????????? 9?????????? 10?????????????????? 11????????????? ?????????????? ??? ?????????? ?????? ?????????????? ???????? ???????????????? ???????? ?????????????? ???????????????? ??? ????????? ????????? ?????????????????? ?????????? ????????????????????????????? ?????????????? ??????????? ??????????????????????????? ??? ???????????? ????????? ?????????????????? ????????? ?????????????????? ?????????????????? ?????????????????? ??????????????????????? -------------------------------------------------------------------------------------------------- ??????? ??????(???????MBA??????????)??????????????????????? ???????????????????????????????????????????????????????? ????????????????????????(?)?????????????????????????????? ?????IBT????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ? ??? ??????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ???????? -------------------------------------------------------------------- ???????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From halaredat at gmail.com Mon Aug 2 07:07:13 2010 From: halaredat at gmail.com (Goris Jeremy) Date: Mon, 2 Aug 2010 15:07:13 +0800 Subject: =?GB2312?B?yczO8bK/ONTCMTTI1bq81t3W0NChsOW0tNK1sOXI2tfKyc8=?= =?GB2312?B?ytC21L3Tu+Fidg==?= Message-ID: ???8?14????????????????bvb -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ??????.doc Type: application/msword Size: 1051136 bytes Desc: not available URL: From oleg at redhat.com Mon Aug 2 12:51:22 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Aug 2010 14:51:22 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100730152025.GA22951@host1.dyn.jankratochvil.net> References: <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730132537.GA15448@host1.dyn.jankratochvil.net> <20100730144124.GA10396@redhat.com> <20100730152025.GA22951@host1.dyn.jankratochvil.net> Message-ID: <20100802125122.GA2267@redhat.com> On 07/30, Jan Kratochvil wrote: > > On Fri, 30 Jul 2010 16:41:24 +0200, Oleg Nesterov wrote: > > IOW, you think that it is better to shift gdbserver into kernel-space than > > port the existing one to the new API or write the new one in user space ? > > So far I just assumed kernel-space ugdb is the plan. As I wrote before I do > not know gdbserver too much. I am not sure, but I do not really know. Jan, all, let me explain again what I think. Yes, as I said I personally do not believe in in-kernel gdbstub too much. If nothing else, I bet it will be never merged upstream. Unless at least this code will also have the more "traditional" user-space API which is immediately clear to the reviewers on lkml. And how we can implement, say, vRun in kernel? I am not saying this is technically impossible, but this against the common sense, imho. Or remote debugging via tcp. We need the user-space helper anyway. Again, of course it is technically possible to create the socket and the kernel thread which serves the requests, but I don't think we should do this. Or two modes, all-stop and non-stop. Imho, the kernel shouldn't even know about this. Or register renumbering. However. I have also said that my opinion doesn't matter. And I meant this! I do not understand the user-space needs, I do not understand the problems from the gdb's pov. So, we can put this code in kernel later, in the same module or another one if this is really needed. At least the prototyping is much easier in user-space. And I hope very much this helps to separate the utrace problems and the protocol problems. I may be wrong, but the most complex "conceptual" part is the thread management. I mean the very basic things: attach, detach, exit, clone. But, from the remore protocol pov these things do not exist, gdbserver hides this details. This is good for gdb, but complicates the testing and surely this is not enough in general. Just think about /bin/strace. Or. Currently I am not sure gdbstub does exactly same as the real gdbserver when the main thread exits. But I do not care at all, it would be trivial to change this user-level code if needed without changing the implementation details in kernel. > Catching up with systemtap's 200x higher software-watchpoint performance over > current (local) gdb (described in "[debug-list] Utrace Discussion Notes" off > this list) could be easier with in-kernel gdb I thought. Perhaps, I can't comment because I do not understand the problem space. Oleg. From oleg at redhat.com Mon Aug 2 18:22:45 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Aug 2010 20:22:45 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100728181702.GA26678@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> Message-ID: <20100802182245.GB16230@redhat.com> On 07/28, Oleg Nesterov wrote: > > - currently it only supports attach, stop, cont, detach > and exit. OK, I am a bit stuck. I am trying to implement attach-to-the-thread-group, and I'd like to invent something simple without O(n**2) and semaphores in ->report_clone(). There are other problems with process-wide ops which should be addressed somehow. Will continue tomorrow... Oleg. From ironically at jaager.nl Mon Aug 2 20:32:03 2010 From: ironically at jaager.nl (Laditka Bartrum) Date: Mon, 02 Aug 2010 22:32:03 +0200 Subject: e made it at an earlie Message-ID: <4C5729AE.9030906@jaager.nl> A non-text attachment was scrubbed... Name: rehouses.rtf Type: application/octet-stream Size: 1312 bytes Desc: not available URL: From loli_burbuja at hotmail.com Mon Aug 2 21:31:56 2010 From: loli_burbuja at hotmail.com (=?gb2312?B?TWFyaSBMb2xpIEyornBleiBBcmVuYXM=?=) Date: Mon, 2 Aug 2010 21:31:56 +0000 Subject: =?gb2312?B?ztLIz86qutzT0LHY0qrIw8Tj1qo=?= =?gb2312?B?tcDV4tCpoaM1OW4=?= Message-ID: ?????? ??????H?????????V????????????F??????????? ?????????F?????100%??22?????P????????X?????? ?????? ??????H?????????? 1.????M????50?????? ????? 2.???A???20????? ????? 3.????P????9???? ???S?? ?????????????8???????????N?????????????? ??????? ps????????????????????Z??????? ????????P??????????K-??17?????? ?????????????P???????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Mon Aug 2 23:53:58 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 3 Aug 2010 01:53:58 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100728181702.GA26678@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> Message-ID: <20100802235358.GA9720@host1.dyn.jankratochvil.net> On Wed, 28 Jul 2010 20:17:02 +0200, Oleg Nesterov wrote: > - the testing was very limited. I played with it about > an hour and didn't find any problems, vut that is all. [...] > Btw, gdb crashes very often right after > > (gdb) set target-async on > (gdb) set non-stop > (gdb) file mt-program > (gdb) target extended-remote :port > (gdb) attach its_pid > > I didn't even try to investigate (this doesn't happen when > it works with the real gdbserver). Just retry, gdb is buggy. Trying it with both /bin/sleep and a threaded testcase and I never got a crash (kernel-2.6.33.6-147.fc13.x86_64 as both host and KVM guest OS). $ killall gdbstub;~/redhat/threadit&p=$!;~/redhat/gdbstub &>~/redhat/out&sleep 0.1;./gdb -nx -ex 'set target-async on' -ex 'set non-stop' -ex "file $HOME/redhat/threadit" -ex 'target extended-remote :2000' -ex "attach $p" -ex 'set confirm no';kill $p; gdbstub: no process killed [6] 22822 [7] 22823 GNU gdb (GDB) 7.2.50.20100802-cvs Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: . Reading symbols from /home/jkratoch/redhat/threadit...done. Remote debugging using :2000 Attached to process 22822 [New Thread 22822.22822] [New Thread 22822.22825] Reading symbols from /lib64/libpthread.so.0...Reading symbols from /usr/lib/debug/lib64/libpthread-2.12.so.debug...done. done. Loaded symbols for /lib64/libpthread.so.0 Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.12.so.debug...done. done. Loaded symbols for /lib64/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.12.so.debug...done. done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 0x00007fead8db6fbd in pthread_join (threadid=140646633633552, thread_return=0x0) at pthread_join.c:89 89 lll_wait_tid (pd->tid); (gdb) [Thread 22822.22825] #2 stopped. 0x00007fead8ad6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) Current language: auto The current source language is "auto; currently asm". info threads 2 Thread 22822.22825 0x00007fead8ad6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 * 1 Thread 22822.22822 0x00007fead8db6fbd in pthread_join (threadid=140646633633552, thread_return=0x0) at pthread_join.c:89 (gdb) q [7]+ Done ~/redhat/gdbstub &>~/redhat/out [6]+ Terminated ~/redhat/threadit Thanks, Jan From oleg at redhat.com Tue Aug 3 12:24:34 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Aug 2010 14:24:34 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100802235358.GA9720@host1.dyn.jankratochvil.net> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> Message-ID: <20100803122434.GA32698@redhat.com> On 08/03, Jan Kratochvil wrote: > > On Wed, 28 Jul 2010 20:17:02 +0200, Oleg Nesterov wrote: > > > Btw, gdb crashes very often right after > > > > (gdb) set target-async on > > (gdb) set non-stop > > (gdb) file mt-program > > (gdb) target extended-remote :port > > (gdb) attach its_pid > > > > I didn't even try to investigate (this doesn't happen when > > it works with the real gdbserver). Just retry, gdb is buggy. ^^^^^^^^^^^^ Yes, I still think gdb is wrong, but please correct me. > Trying it with both /bin/sleep and a threaded testcase and I never got a crash > (kernel-2.6.33.6-147.fc13.x86_64 as both host and KVM guest OS). To clarify, let me repeat: I never saw such a crash with the real gdbserver, but this often happens in my testing. I think I understand what happens. And this leads to the question about the %Stop notifications which I was going to delay, see below. I just reproduced the crash. I entered the following commands via CLI interface: (gdb) set target-async on (gdb) set non-stop (gdb) target extended-remote :2000 (gdb) file mt Everything is OK so far. "mt" is not interesting, just the simple application with 4 sleeping threads. Then gdb crashes during attach: (gdb) attach 24291 Attached to process 24291 [New Thread 24291.24291] [New Thread 24291.24292] [New Thread 24291.24293] [New Thread 24291.24294] Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done. Loaded symbols for /lib64/libpthread.so.0 Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib64/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 0x000000375faf21ce in __lll_lock_wait_private () from /lib64/libc.so.6 (gdb) [Thread 24291.24293] #3 stopped. 0x000000375faf21ce in __lll_lock_wait_private () from /lib64/libc.so.6 [Thread 24291.24292] #2 stopped. 0x000000375fad65cb in read () from /lib64/libc.so.6 [Thread 24291.24291] #1 stopped. 0x00000033af60e57d in pause () from /lib64/libpthread.so.0 inline-frame.c:335: internal-error: skip_inline_frames: Assertion `find_inline_frame_state (ptid) == NULL' failed. A problem internal to GDB has been detected, And I think this is because of %Stop issues. >From gdb.info Because the notification mechanism is unreliable, the stub is permitted to resend a stop reply notification if it believes GDB may not have received it. GDB ignores additional stop reply notifications received before it has finished processing a previous notification and the stub has completed sending any queued stop events. So I assumed it is always safe to resend the notification unless gdb already sent vStopped. Since it is not clear to me when it makes sense to resend it, currently gdbstub does re-send every time /proc/ugdb reports the new event (T00 in this case). I agree this is not optimal, but this looks correct to me. However, gdb.info also states: Only one stop reply notification at a time may be pending; if additional stop events occur before GDB has acknowledged the previous notification, they must be queued by the stub for later synchronous transmission in response to `vStopped' packets from GDB. That is why gdbstub re-sends the same notification, until it gets vStopped. Now let's look into the log: => vAttach;5ee3 <= OK => qfThreadInfo <= mp5ee3.5ee3,p5ee3.5ee4,p5ee3.5ee5,p5ee3.5ee6 => qsThreadInfo <= l => Hgp5ee3.5ee3 <= OK => vCont? <= vCont;t;c;C;s;S => vCont;t:p5ee3.-1 <= OK Note: gdbstub reports OK before any thread actually stops. I believe this is correct from the remote protocol pov, and this is what we want. <= Stop:T00thread:p5ee3.5ee4; Some thread actually stops, we sent the notification. <= Stop:T00thread:p5ee3.5ee4; Another threads stops, gdbstub resends the same notification according to the docs above (or according to my understanding). Note: this doesn't happen _every time_. In the more likely case all threads are already stopped when ->poll() succeeds. But sometimes some thread stops a little bit later. Once again, please note that both notifications are the same thing, but I guess gdb doesn't understand this, see below. Then, => vStopped <= T00thread:p5ee3.5ee3; => vStopped <= T00thread:p5ee3.5ee6; => vStopped <= T00thread:p5ee3.5ee5; => vStopped <= OK => Hgp5ee3.5ee4 <= OK => g <= 00feffffffffffffa066d65f37000000ffffffffffffffff00040000000... [...snip a lot of $m packets ] everything is fine so far. Then, => vCont;t:p5ee3.-1 <= OK Well. I hope this 'OK' without the subsequent notifications matches the documentation: vCont[;ACTION[:THREAD-ID]]... ... The `t' action is only relevant in non-stop mode ... A stop reply should be generated for any affected thread not already stopped. IIUC, "already stopped" means "already reported as stopped to gdb". So gdbstub replies 'OK' and doesn't send any %Stop packets, but gdb seems to expect the new STOP-REPLY packets: => m375fad65cb,1 <= 48 => m375fad65cb,1 <= 48 => vStopped And what should I do in this case??? Probably, this vStopped pairs the _second_ notification above. But gdbstub has already acked this notification during the previous vStopped sequence. E01? This seems to confuse gdb. >From gdb.info `vStopped' In non-stop mode (*note Remote Non-Stop::), acknowledge a previous stop reply and prompt for the stub to report another one. Reply: `Any stop packet' if there is another unreported stop event (*note Stop Reply Packets::) `OK' if there are no unreported stop events So I am sending 'OK' because there are no unreported stop events. But this seems to confuse gdb, it thinks this this 'OK' acks the second notification, <= OK => Hgp5ee3.5ee3 <= OK => g <= fefdffffffffffff0000000000000000ffffffffffffffff02000000000... => m33af60e57d,1 <= 48 => m33af60e57d,1 <= 48 => Hgp5ee3.5ee6 <= OK => g <= 00feffffffffffffa066d65f37000000ffffffffffffffff02000000000... => m375faf21ce,1 <= 89 => m375faf21ce,1 <= 89 => Hgp5ee3.5ee3 <= OK => g <= fefdffffffffffff0000000000000000ffffffffffffffff02000000000... => m33af60e57d,1 <= 48 => m33af60e57d,1 <= 48 => Hgp5ee3.5ee5 <= OK => g <= 00feffffffffffffa066d65f37000000ffffffffffffffff02000000000... => m375faf21ce,1 <= 89 => m375faf21ce,1 <= 89 => Hgp5ee3.5ee3 <= OK => g <= fefdffffffffffff0000000000000000ffffffffffffffff02000000000... => m33af60e57d,1 <= 48 => m33af60e57d,1 <= 48 => Hgp5ee3.5ee4 <= OK Note: _this_ thread was reported twice via %Stop. => g <= 00feffffffffffffa066d65f37000000ffffffffffffffff00040000000... Amen, gdb crashes. Indeed, it has already looked at this thread (see another Hgp5ee3.5ee4 above). Jan, I am not sure but _IIRC_ I observed other scenarios when gdb crashes during the attach, but can't reproduce right now. ========================================================================== Now, let's talk about %Stop. I must admit, I believe the idea behind %Stop in its current state is not very good. First of all, it is not clear how this all can be implemented correctly. Forget about the multithreading, consider the simplest case: gdb tracees the single thread, this thread stops, gdbserver sends '%Stop:T00thread:pPID.PID;'. >From gdb.info: After receiving a stop reply notification, GDB shall acknowledge it by sending a `vStopped' packet (*note vStopped packet::) as a regular, synchronous request to the stub. Such acknowledgment is not required to happen immediately, as GDB is permitted to send other, unrelated packets to the stub first, which the stub should process normally. Very nice. Suppose that, before sending vStopped, gdb sends 'D;PID'. Then it sends vStopped. How should gdbstub reply? - OK seems incorrect, it acks the previous T00 but this thread/process is already detached. - E01? probably, but this is not documented and surely it is not right if we have other events to reply (say, multiple inferiors). - But, any other reply (especially if we have other stop events to reply) acks the previous T00 which is no longer true! Or, instead of detach from gdb, suppose that the the tracee changes its state by the time gdb sends vStopped in reply to %Stop. Say, it is SIGKILL'ed. There is no way to let gdb know its state was already changed. We can only ack the state which was reported previously. And there is no way to inform gdb there is nothing new and nothing to ack because the previous notification was already acked (like it happens during the crash). And probably this crash (if my understanding is correct) at least proves that the current scheme is not very convenient. I do not suggest to discuss this right now, but perhaps we can have a stateless notification? Say, just '%Stop#..' which informs gdb it has some events to get via 'vStopped'. In this case any reply to vStopped does not ack the history, but reports the new event or 'OK' if no more events. This is at least very understandable and clear. And simpler. Oleg. From oleg at redhat.com Tue Aug 3 13:14:36 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Aug 2010 15:14:36 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100803122434.GA32698@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> <20100803122434.GA32698@redhat.com> Message-ID: <20100803131436.GA2185@redhat.com> Forgot to mention, On 08/03, Oleg Nesterov wrote: > > So I assumed it is always safe to resend the notification unless gdb already > sent vStopped. Since it is not clear to me when it makes sense to resend it, > currently gdbstub does re-send every time /proc/ugdb reports the new event > (T00 in this case). I agree this is not optimal, but this looks correct to me. I'll change gdbstub to never resend the notification to avoid the problem. But probably gdb should be fixed anyway. And, now I recalled why I added resend into the initial code. This is because I hit another minor problem which I misinterpreted as if gdb can miss the notification. To avoid the unnecessary details, consider the oversimplified example, $ sleep 10000& [1] 2923 $ cat > SLEEP set target-async on set non-stop target extended-remote :2000 file /bin/sleep attach 2923 info registers detach ^D $ gdb This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: . (gdb) (gdb) (gdb) Remote debugging using :2000 (gdb) Reading symbols from /bin/sleep...(no debugging symbols found)...done. (gdb) Attached to process 2923 [New Thread 2923.2923] Target is executing. (gdb) Detached from remote process 2923. (gdb) quit And yes, gdb ignores %Stop and just detaches. But this is because of another issue (which looks like a minor gdb bug to me), note the "Target is executing." above. This is the reply to "info registers". Why? OK, yes, it is executing. Then send vCont:t ? "attach PID" means attach and stop it, no? And note, the same commands work as expected in CLI mode. I also tried to add "interrupt" before "info registers", this doesn't help although in this case gdb does send vStopped. Can't resist, I spent a lot of time trying to understand what is wrong. Because at first I played with the real gdbserver via CLI to ensure everything works as I expect, then I tried to achieve the same results with /proc/ugdb doing "$ gdb < BATCH_FILE" with the same commands. Oleg. From jan.kratochvil at redhat.com Tue Aug 3 13:36:27 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 3 Aug 2010 15:36:27 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100803131436.GA2185@redhat.com> <20100803122434.GA32698@redhat.com> Message-ID: <20100803133627.GB16669@host1.dyn.jankratochvil.net> On Tue, 03 Aug 2010 14:24:34 +0200, Oleg Nesterov wrote: > On 08/03, Jan Kratochvil wrote: > > On Wed, 28 Jul 2010 20:17:02 +0200, Oleg Nesterov wrote: > > Trying it with both /bin/sleep and a threaded testcase and I never got a crash > > (kernel-2.6.33.6-147.fc13.x86_64 as both host and KVM guest OS). > > To clarify, let me repeat: I never saw such a crash with the real > gdbserver, but this often happens in my testing. I am also testing it with your ugdb.c and gdbstub. On Tue, 03 Aug 2010 15:14:36 +0200, Oleg Nesterov wrote: > On 08/03, Oleg Nesterov wrote: > > > > So I assumed it is always safe to resend the notification unless gdb already > > sent vStopped. Since it is not clear to me when it makes sense to resend it, > > currently gdbstub does re-send every time /proc/ugdb reports the new event > > (T00 in this case). I agree this is not optimal, but this looks correct to me. > > I'll change gdbstub to never resend the notification to avoid the problem. Yes, I has been now just writing you such reply. > But probably gdb should be fixed anyway. There are so many serious bugs in GDB affecting regular GDB usage... > To avoid the unnecessary details, consider the oversimplified example, > > $ sleep 10000& > [1] 2923 > > $ cat > SLEEP > set target-async on > set non-stop > target extended-remote :2000 > file /bin/sleep > attach 2923 > info registers > detach > ^D > > $ gdb GNU gdb (GDB) 7.1 > Copyright (C) 2010 Free Software Foundation, Inc. > License GPLv3+: GNU GPL version 3 or later > This is free software: you are free to change and redistribute it. > There is NO WARRANTY, to the extent permitted by law. Type "show copying" > and "show warranty" for details. > This GDB was configured as "x86_64-unknown-linux-gnu". > For bug reporting instructions, please see: > . > (gdb) (gdb) (gdb) Remote debugging using :2000 > (gdb) Reading symbols from /bin/sleep...(no debugging symbols found)...done. > (gdb) Attached to process 2923 > [New Thread 2923.2923] > Target is executing. > (gdb) Detached from remote process 2923. > (gdb) quit > > And yes, gdb ignores %Stop and just detaches. But this is because > of another issue (which looks like a minor gdb bug to me), note the > > "Target is executing." > > above. This is the reply to "info registers". Why? OK, yes, it is > executing. Yes. > Then send vCont:t ? "attach PID" means attach and stop it, no? But it is not yet stopped that time. > Can't resist, I spent a lot of time trying to understand what is wrong. Nothing, you should wait till GDB reports the inferior has stopped. It is easy/normal in the GDB testsuite and by FE (Front Ends). I understand it is not convenient from -ex or -x argument. There could be probably some async-only command besides `interrupts', also some `wait-till-stopped'. > I tried to achieve the same results with /proc/ugdb doing > "$ gdb < BATCH_FILE" with the same commands. Maybe you can write a new *.exp testcase for such testing. Thanks, Jan From jan.kratochvil at redhat.com Tue Aug 3 13:54:51 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 3 Aug 2010 15:54:51 +0200 Subject: gdbstub initial code, another approach In-Reply-To: <20100802125122.GA2267@redhat.com> References: <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100730125755.GA6438@redhat.com> <20100730132537.GA15448@host1.dyn.jankratochvil.net> <20100730144124.GA10396@redhat.com> <20100730152025.GA22951@host1.dyn.jankratochvil.net> <20100802125122.GA2267@redhat.com> Message-ID: <20100803135451.GA30848@host1.dyn.jankratochvil.net> On Mon, 02 Aug 2010 14:51:22 +0200, Oleg Nesterov wrote: > Yes, as I said I personally do not believe in in-kernel gdbstub too much. > If nothing else, I bet it will be never merged upstream. Unless at least > this code will also have the more "traditional" user-space API which is > immediately clear to the reviewers on lkml. I find knfsd is a precedent, isn't it? It contains some compatibility-kludges (such as the SUNRPC layer used only for nfs) and still the filesystem operations are AFAIK fully kernel-side. NFS is a well-established protocol such as the gdbserver one and both need high performance of their server-side execution. > Or remote debugging via tcp. We need the user-space helper anyway. There is rpc.nfsd as the userland wrapper, I do not find a problem if such program would exist for ugdb. > Or two modes, all-stop and non-stop. Imho, the kernel shouldn't even > know about this. Or register renumbering. The NFS protocol also isn't perfect. Thanks, Jan From oleg at redhat.com Tue Aug 3 15:06:56 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Aug 2010 17:06:56 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100803133627.GB16669@host1.dyn.jankratochvil.net> References: <20100803131436.GA2185@redhat.com> <20100803122434.GA32698@redhat.com> <20100803133627.GB16669@host1.dyn.jankratochvil.net> Message-ID: <20100803150656.GA8043@redhat.com> On 08/03, Jan Kratochvil wrote: > > On Tue, 03 Aug 2010 14:24:34 +0200, Oleg Nesterov wrote: > > > > > > So I assumed it is always safe to resend the notification unless gdb already > > > sent vStopped. Since it is not clear to me when it makes sense to resend it, > > > currently gdbstub does re-send every time /proc/ugdb reports the new event > > > (T00 in this case). I agree this is not optimal, but this looks correct to me. > > > > I'll change gdbstub to never resend the notification to avoid the problem. > > Yes, I has been now just writing you such reply. Sure, will do. > > But probably gdb should be fixed anyway. > > There are so many serious bugs in GDB affecting regular GDB usage... OK, so I assume that the current behaviour of gdbstub is correct, even if stupid. > > To avoid the unnecessary details, consider the oversimplified example, > > > > $ sleep 10000& > > [1] 2923 > > > > $ cat > SLEEP > > set target-async on > > set non-stop > > target extended-remote :2000 > > file /bin/sleep > > attach 2923 > > info registers > > detach > > ^D > > > > $ gdb > GNU gdb (GDB) 7.1 > > Copyright (C) 2010 Free Software Foundation, Inc. > > License GPLv3+: GNU GPL version 3 or later > > This is free software: you are free to change and redistribute it. > > There is NO WARRANTY, to the extent permitted by law. Type "show copying" > > and "show warranty" for details. > > This GDB was configured as "x86_64-unknown-linux-gnu". > > For bug reporting instructions, please see: > > . > > (gdb) (gdb) (gdb) Remote debugging using :2000 > > (gdb) Reading symbols from /bin/sleep...(no debugging symbols found)...done. > > (gdb) Attached to process 2923 > > [New Thread 2923.2923] > > Target is executing. > > (gdb) Detached from remote process 2923. > > (gdb) quit > > > > And yes, gdb ignores %Stop and just detaches. But this is because > > of another issue (which looks like a minor gdb bug to me), note the > > > > "Target is executing." > > > > above. This is the reply to "info registers". Why? OK, yes, it is > > executing. > > Yes. > > > > Then send vCont:t ? "attach PID" means attach and stop it, no? > > But it is not yet stopped that time. Well. And how can I stop it? Once again, this all works in CLI mode. And this looks very natural (gdb) attach PID (gdb) info registers As a newbie user of gdb, I expected it is gdb who should take care and stop the tracee after "attach". And please remember, "interrupt" doesn't help. OK, please ignore. Now that I know I can't trust 'gdb < BATCH' I do not use this. > > Can't resist, I spent a lot of time trying to understand what is wrong. > > Nothing, you should wait till GDB reports the inferior has stopped. Yes, yes, now I understand this. Once again, I was greatly confused because I didn't know that CLI mode makes the difference. Even if I enter the commands via copy-and-paste, gdb always "completes" this attach before it reacts to "info registers". And there were other issues which I didn't understand when I tried to solve this problem... > It is > easy/normal in the GDB testsuite Hmm. How? probably the tests in testsuite wait for something which looks like "[Thread 5683.5683] #1 stopped." from gdb? > > I tried to achieve the same results with /proc/ugdb doing > > "$ gdb < BATCH_FILE" with the same commands. > > Maybe you can write a new *.exp testcase for such testing. I guess you want me to learn /usr/bin/expect ;) Oleg. From jan.kratochvil at redhat.com Tue Aug 3 15:55:21 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 3 Aug 2010 17:55:21 +0200 Subject: Q: multiple inferiors, all-stop && vCont In-Reply-To: <20100803150656.GA8043@redhat.com> <20100803143004.GB2185@redhat.com> Message-ID: <20100803155521.GA3226@host1.dyn.jankratochvil.net> On Tue, 03 Aug 2010 16:30:04 +0200, Oleg Nesterov wrote: > However, I do not really understand how this can work reliably in the > terms of remote protocol. Somehow this scheme relies on the fact that > gdb will send another vCont;t:pTGID.-1 _once again_ after the previous > vCont;t:pTGID.-1, and gdbserver can report the other threads via > Stop/vStopped. OK, I hope this doesn't matter. attach_command_post_wait: /* At least the current thread is already stopped. */ /* In all-stop, by definition, all threads have to be already stopped at this point. In non-stop, however, although the selected thread is stopped, others may still be executing. Be sure to explicitly stop all threads of the process. This should have no effect on already stopped threads. */ if (non_stop) target_stop (pid_to_ptid (inferior->pid)); > Yes. And please note that at least in-kernel gdbstub can not use > libthread_db. But, I also hope that we can avoid it even if gdbstub > runs in user-space ? As far as I understand it now in-kernel gdbserver does not need libthread_db at all. The communication is based only on PID/TID anyway and on Linux we do not need libthread_db to enumerate the TIDs of a PID. > > Even FSF gdbserver does not seem to use/provide pthread_t identifiers: > > 2 Thread 23487.23490 0x00007fb25c983a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 > > * 1 Thread 23487.23487 0x00007fb25cc63fbd in pthread_join (threadid=140404033701648, thread_return=0x0) at pthread_join.c:89 > > > > as provided by local linux-nat.c / linux-thread-db.c. > > 2 Thread 0x7ffff7842710 (LWP 23503) 0x00007ffff78e9a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 > > * 1 Thread 0x7ffff7ff3700 (LWP 23500) 0x00007ffff7bc9fbd in pthread_join (threadid=140737346021136, thread_return=0x0) at pthread_join.c:89 > > > > The LWP -> thread_t conversion could be done later from the client side only > > using: > > libthread_db (td_ta_map_lwp2thr(), td_thr_get_info(), > > typeof (td_thrinfo_t->ti_tid) = thread_t) > > Cough. This is black magic to me ;) This was more just a comment how to bring FSF gdbserver (or ugdb) on-par with local linux-nat.c. This is a future extension, so far I believe we should more get udb on-par with FSF gdbserver. FSF gdbserver itself already does not support displaying pthread_t IIUC. > I probably understand what pthread_t is, but I do not know how/if this > is important for gdb. As all the pthread_* functions in inferior use pthread_t it is generally useful to be able to associate pthread_t inferior values with the live threads being debugged. > Should I worry about this issue right now? The pthread_t / libthread_db stuff should be probably only the GDB client problem. You will probably never face it. > And, I hope that "client side only using: libthread_db" means gdb, not > gdbserver ? yes, I have meant it that way. > > why do you want from GDB to use specifically `vCont:c'? > > Because, first of all, I wanted to understand why gdb doesn't send > vCont:c to me, but uses this command when it works with the real > gdbserver. Anyway I see GDB uses `vCont;c' even with gdbstub so this problem is not reproducible for me. => $vCont;c:p658.658 <= $OK On Tue, 03 Aug 2010 17:06:56 +0200, Oleg Nesterov wrote: > > > But probably gdb should be fixed anyway. > > > > There are so many serious bugs in GDB affecting regular GDB usage... > > OK, so I assume that the current behaviour of gdbstub is correct, even > if stupid. Yes, so far I do not see problems on the gdbstub side. > > > Then send vCont:t ? "attach PID" means attach and stop it, no? > > > > But it is not yet stopped that time. > > Well. And how can I stop it? > > Once again, this all works in CLI mode. And this looks very natural What do you call CLI mode? We use only CLI mode so far all the time. The other mode is MI (`gdb -i=mi'). We can talk about local (=linux-nat.c, default without `target *remote') mode or remote (=remote.c, `target extended-remote') mode. With CLI remote mode with FSF gdbserver it also errors on: killall gdbserver gdbstub;~/redhat/threadit&p=$!;./gdbserver/gdbserver --remote-debug --multi :2000 &>~/redhat/out&sleep 0.1;./gdb -nx -ex 'set target-async on' -ex 'set non-stop' -ex "file $HOME/redhat/threadit" -ex 'target extended-remote :2000' -ex "attach $p" -ex 'set confirm no' -ex bt;kill $p; ... Target is executing. With CLI remote mode with gdbstub it also errors on: killall -9 gdbserver gdbstub;sleep 0.5;~/redhat/threadit&p=$!;~/redhat/gdbstub &>~/redhat/out&sleep 0.1;./gdb -nx -ex 'set target-async on' -ex 'set non-stop' -ex "file $HOME/redhat/threadit" -ex 'target extended-remote :2000' -ex "attach $p" -ex 'set confirm no' -ex bt;kill $p ... Target is executing. With CLI local mode it prints a bogus backtrace: killall -9 gdbserver gdbstub;sleep 0.5;~/redhat/threadit&p=$!;sleep 0.1;./gdb -nx -ex 'set target-async on' -ex 'set non-stop' -ex "file $HOME/redhat/threadit" -ex "attach $p" -ex 'set confirm no' -ex bt;kill $p ... #0 0x00007fbc1989cfbd in ?? () #1 0x00007fff7f643110 in ?? () #2 0x00007fbc19ac5795 in ?? () #3 0x00007fbc1989ce90 in ?? () #4 0x00007fbc19515d38 in ?? () #5 0x00007fbc177129e0 in ?? () #6 0x0000000000000000 in ?? () later: #0 0x00007fbc1989cfbd in pthread_join (threadid=140445855340304, thread_return=0x0) at pthread_join.c:89 #1 0x000000000040074c in main () at threadit.c:30 > As a newbie user of gdb, I expected it is gdb who should take care > and stop the tracee after "attach". This was this way in the sync/all-stop mode. In async/non-stop mode it is intentionally asynchronous: attach_command: if (target_can_async_p ()) add_inferior_continuation (attach_command_continuation, a, attach_command_continuation_free_args); return; It may take some time before this inferior reports us back the stop and we may want to debug other inferiors in the meantime. > And please remember, "interrupt" doesn't help. You need "wait-till-inferior-completes-interrupt" (which does not exist), not "interrupt" which means "start-asynchronous-inferior-interruption". > Yes, yes, now I understand this. Once again, I was greatly confused > because I didn't know that CLI mode makes the difference. Even if I ^^^ local (=non-remote) probably > enter the commands via copy-and-paste, gdb always "completes" this > attach before it reacts to "info registers". It does not work before the target stops anyway in the local mode. Trying to access thread data while the thread is running can give stale data without printing an error. It is probably expected FE (Front End - such as Eclipse) takes care of it anyway. > > It is easy/normal in the GDB testsuite > > Hmm. How? probably the tests in testsuite wait for something which > looks like "[Thread 5683.5683] #1 stopped." from gdb? Yes, see gdb/testsuite/gdb.mi/mi-nonstop.exp for all its mi_expect_stop calls. But that is the MI mode, not CLI mode, with commands like: -break-insert -t main Thanks, Jan From oleg at redhat.com Tue Aug 3 16:53:59 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Aug 2010 18:53:59 +0200 Subject: Q: multiple inferiors, all-stop && vCont In-Reply-To: <20100803155521.GA3226@host1.dyn.jankratochvil.net> References: <20100803150656.GA8043@redhat.com> <20100803143004.GB2185@redhat.com> <20100803155521.GA3226@host1.dyn.jankratochvil.net> Message-ID: <20100803165359.GA11274@redhat.com> On 08/03, Jan Kratochvil wrote: > > On Tue, 03 Aug 2010 16:30:04 +0200, Oleg Nesterov wrote: > > However, I do not really understand how this can work reliably in the > > terms of remote protocol. Somehow this scheme relies on the fact that > > gdb will send another vCont;t:pTGID.-1 _once again_ after the previous > > vCont;t:pTGID.-1, and gdbserver can report the other threads via > > Stop/vStopped. OK, I hope this doesn't matter. > > attach_command_post_wait: > > /* At least the current thread is already stopped. */ > > /* In all-stop, by definition, all threads have to be already > stopped at this point. In non-stop, however, although the > selected thread is stopped, others may still be executing. > Be sure to explicitly stop all threads of the process. This > should have no effect on already stopped threads. */ > if (non_stop) > target_stop (pid_to_ptid (inferior->pid)); This just reflects the current situation with the current implementation. gdb already did vAttach;PID vCont;t:pPID.-1 I do not see anything in the _documentation_ which could explain that only the main thread can be stopped despite the fact "-1" means all threads. Once again, I already understand why gdb + gdbserver work this way, I meant remote protocol "in general". And in fact, I do not think your explanation is correct. Yes, this attach_command_post_wait() is called during attach. But even after that gdbserver reports only the main thread. This happens before qSymbol stage. Only when gdb issues yet _another_ vCont;t:pPID.-1 after that, gdbserver reports other threads, and this have nothing to do (I think) with attach_command_post_wait(). In fact, to me this all works _contrary_ to the comment above. Be sure to explicitly stop all threads of the process. This doesn't happen. But, it is very possible I missed something. Ang again, I think (I hope ;) we can forget this because the simple method works too. > > Yes. And please note that at least in-kernel gdbstub can not use > > libthread_db. But, I also hope that we can avoid it even if gdbstub > > runs in user-space ? > > As far as I understand it now in-kernel gdbserver does not need libthread_db > at all. The communication is based only on PID/TID anyway and on Linux we do > not need libthread_db to enumerate the TIDs of a PID. Yes, thanks. This is what I meant. I was afraid there are some other reason why we can't avoid libthread_db. > > Should I worry about this issue right now? > > The pthread_t / libthread_db stuff should be probably only the GDB client > problem. You will probably never face it. > > > And, I hope that "client side only using: libthread_db" means gdb, not > > gdbserver ? > > yes, I have meant it that way. Great, thanks. > > > why do you want from GDB to use specifically `vCont:c'? > > > > Because, first of all, I wanted to understand why gdb doesn't send > > vCont:c to me, but uses this command when it works with the real > > gdbserver. > > Anyway I see GDB uses `vCont;c' even with gdbstub so this problem is not > reproducible for me. > > => $vCont;c:p658.658 > <= $OK Yes. From another email from me: OK. After I read remote_vcont_resume()->remote_vcont_probe() path I understand why 'vCont;c;t' doesn't work. Contrary to what the documentation says it is all or nothing. Except 't' has the separate remote_state->support_vCont_t flag. Very strange. That is why gdbstub reports 'vCont;t;c;C;s;S' to 'vCont?', despite the fact it doesn't implement C/s/S yet. > > > But it is not yet stopped that time. > > > > Well. And how can I stop it? > > > > Once again, this all works in CLI mode. And this looks very natural > > What do you call CLI mode? We use only CLI mode so far all the time. The > other mode is MI (`gdb -i=mi'). Sorry for confusion, I do not know how to name it correctly... I can start gdb and then enter these commands by hand, this is what I called CLI (command line interface ;). And in this case everything works as I expected. Or I can put these command into the file FILE, and then do "$ gdb < FILE". In this case "attach" + "info registers" doesn't work. I didn't try "gdb -nx -ex ..." method yet. Otherwise, I always use remote mode. > This was this way in the sync/all-stop mode. In async/non-stop mode it is > intentionally asynchronous: > > attach_command: > if (target_can_async_p ()) > add_inferior_continuation (attach_command_continuation, a, > attach_command_continuation_free_args); > return; > > It may take some time before this inferior reports us back the stop and we may > want to debug other inferiors in the meantime. Yes, I see, > > Yes, yes, now I understand this. Once again, I was greatly confused > > because I didn't know that CLI mode makes the difference. Even if I > ^^^ local (=non-remote) probably no, please see above. And sorry for confusion again. So. To summarise, I never claimed this is a bug. OTOH, I think this difference can confuse a newbie like me. Yes, I do understand vAttach issues, but I thought that "attach" command should always hide these details. From the documentation: attach PROCESS-ID ... The first thing GDB does after arranging to debug the specified process is to stop it. You can examine and modify an attached process with all the GDB commands that are ordinarily available when you start processes with `run'. You can insert breakpoints; you can step and continue; you can modify storage. If you would rather the process continue running, you may use the `continue' command after attaching GDB to the process. Oleg. From jan.kratochvil at redhat.com Tue Aug 3 18:36:40 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 3 Aug 2010 20:36:40 +0200 Subject: Q: multiple inferiors, all-stop && vCont In-Reply-To: <20100803165359.GA11274@redhat.com> References: <20100803150656.GA8043@redhat.com> <20100803143004.GB2185@redhat.com> <20100803155521.GA3226@host1.dyn.jankratochvil.net> <20100803165359.GA11274@redhat.com> Message-ID: <20100803183640.GA27303@host1.dyn.jankratochvil.net> On Tue, 03 Aug 2010 18:53:59 +0200, Oleg Nesterov wrote: > On 08/03, Jan Kratochvil wrote: > > On Tue, 03 Aug 2010 16:30:04 +0200, Oleg Nesterov wrote: > > > However, I do not really understand how this can work reliably in the > > > terms of remote protocol. Somehow this scheme relies on the fact that > > > gdb will send another vCont;t:pTGID.-1 _once again_ after the previous > > > vCont;t:pTGID.-1, and gdbserver can report the other threads via > > > Stop/vStopped. OK, I hope this doesn't matter. > > > > attach_command_post_wait: > > > > /* At least the current thread is already stopped. */ > > > > /* In all-stop, by definition, all threads have to be already > > stopped at this point. In non-stop, however, although the > > selected thread is stopped, others may still be executing. > > Be sure to explicitly stop all threads of the process. This > > should have no effect on already stopped threads. */ > > if (non_stop) > > target_stop (pid_to_ptid (inferior->pid)); > > This just reflects the current situation with the current implementation. > gdb already did > > vAttach;PID > vCont;t:pPID.-1 > > I do not see anything in the _documentation_ which could explain that > only the main thread can be stopped despite the fact "-1" means all > threads. "-1" really means all threads - all those gdbserver knows about that time. Anyway this double-stop issue is gdbserver/libthread_db specific and offtopic for ugdb. > Once again, I already understand why gdb + gdbserver work this way, > I meant remote protocol "in general". In remote protocol - and even internally in gdbserve - "-1" really always means all the (currently known) threads. > And in fact, I do not think your explanation is correct. Yes, this > attach_command_post_wait() is called during attach. But even after that > gdbserver reports only the main thread. This happens before qSymbol > stage. This attach_command_post_wait code is executed after the qSymbol command. The first single-thread vCont: #0 putpkt (buf=0x1f348b0 "vCont;t:p517.-1") at remote.c:6730 #1 in remote_stop_ns (ptid=...) at remote.c:4709 #2 in remote_stop (ptid=...) at remote.c:4747 #3 in target_stop (ptid=...) at target.c:3031 #4 in attach_command (args=0x7fffffffd861 "1303", from_tty=1) at infcmd.c:2436 #5 in do_cfunc (c=0x1db8bf0, args=0x7fffffffd861 "1303", from_tty=1) at ./cli/cli-decode.c:67 #6 in cmd_func (cmd=0x1db8bf0, args=0x7fffffffd861 "1303", from_tty=1) at ./cli/cli-decode.c:1771 #7 in execute_command (p=0x7fffffffd864 "3", from_tty=1) at top.c:422 #8 in catch_command_errors (command=0x48a3e3 , arg=0x7fffffffd85a "attach 1303", from_tty=1, mask=6) at exceptions.c:534 #9 in captured_main (data=0x7fffffffd360) at ./main.c:887 The second all-threads vCont: #0 putpkt (buf=0x1f4ecb0 "vCont;t:p517.-1") at remote.c:6730 #1 in remote_stop_ns (ptid=...) at remote.c:4709 #2 in remote_stop (ptid=...) at remote.c:4747 #3 in target_stop (ptid=...) at target.c:3031 #4 in attach_command_post_wait (args=0x1f3b6f0 "1303", from_tty=1, async_exec=0) at infcmd.c:2334 #5 in attach_command_continuation (args=0x1f3b6a0) at infcmd.c:2355 #6 in do_my_cleanups (pmy_chain=0x7fffffffcd08, old_chain=0x0) at utils.c:421 #7 in do_all_inferior_continuations () at utils.c:692 #8 in inferior_event_handler (event_type=INF_EXEC_COMPLETE, client_data=0x0) at inf-loop.c:96 #9 in fetch_inferior_event (client_data=0x0) at infrun.c:2649 #10 in fetch_inferior_event_wrapper (client_data=0x0) at inf-loop.c:169 #11 in catch_errors (func=0x6b4287 , func_args=0x0, errstring=0xe378dd "", mask=6) at exceptions.c:518 #12 in inferior_event_handler (event_type=INF_REG_EVENT, client_data=0x0) at inf-loop.c:65 #13 in remote_async_serial_handler (scb=0x1f30b00, context=0x0) at remote.c:10317 #14 in push_event (context=0x1f30b00) at ser-base.c:176 #15 in handle_timer_event (dummy=...) at event-loop.c:1306 #16 in process_event () at event-loop.c:399 #17 in gdb_do_one_event (data=0x0) at event-loop.c:452 #18 in catch_errors (func=0x6b0d2a , func_args=0x0, errstring=0xe07943 "", mask=6) at exceptions.c:518 #19 in tui_command_loop (data=0x0) at ./tui/tui-interp.c:171 #20 in current_interp_command_loop () at interps.c:291 #21 in captured_command_loop (data=0x0) at ./main.c:227 #22 in catch_errors (func=0x47ff66 , func_args=0x0, errstring=0xdc6967 "", mask=6) at exceptions.c:518 #23 in captured_main (data=0x7fffffffd360) at ./main.c:910 > But, it is very possible I missed something. Ang again, I think (I hope ;) > we can forget this because the simple method works too. This discussion is really offtopic for ugdb. > I was afraid there are some other reason why we can't avoid libthread_db. Roland has correctly pointed out the TLS support. But that will come later. > Yes, I do understand vAttach issues, but I thought that "attach" > command should always hide these details. From the documentation: > > attach PROCESS-ID > > ... > The first thing GDB does after arranging to debug the specified > process is to stop it. You can examine and modify an attached process > with all the GDB commands that are ordinarily available when you start > processes with `run'. You can insert breakpoints; you can step and > continue; you can modify storage. If you would rather the process > continue running, you may use the `continue' command after attaching > GDB to the process. It is true "attach" stops the inferior. Just the stop completes only after the "attach" command returns. Regards, Jan From kevinb at redhat.com Tue Aug 3 19:56:51 2010 From: kevinb at redhat.com (Kevin Buettner) Date: Tue, 3 Aug 2010 12:56:51 -0700 Subject: Q: %Stop && gdb crash In-Reply-To: <20100803131436.GA2185@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> <20100803122434.GA32698@redhat.com> <20100803131436.GA2185@redhat.com> Message-ID: <20100803125651.009f0f07@mesquite.lan> On Tue, 3 Aug 2010 15:14:36 +0200 Oleg Nesterov wrote: > To avoid the unnecessary details, consider the oversimplified example, > > $ sleep 10000& > [1] 2923 > > $ cat > SLEEP > set target-async on > set non-stop > target extended-remote :2000 > file /bin/sleep > attach 2923 > info registers > detach > ^D I'd be curious to know if the behavior improves when you omit "set target-async on" and "set non-stop". Kevin From casakirin at gmail.com Tue Aug 3 21:44:36 2010 From: casakirin at gmail.com (Leighty Steed) Date: Wed, 4 Aug 2010 05:44:36 +0800 Subject: =?GB2312?B?yczO8bK/ONTCMTTI1bq81t3W0NChsOW0tNK1sOXI2tfKyc8=?= =?GB2312?B?ytC21L3Tu+E=?= Message-ID: ???8?14???????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ?????.doc Type: application/msword Size: 1051648 bytes Desc: not available URL: From bni at hwer.com Wed Aug 4 05:33:26 2010 From: bni at hwer.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Wed, 4 Aug 2010 13:33:26 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyfqy+s/Ws6HOo7v61KS3wNPrv9jWxg==?= Message-ID: <201008040533.o745XK6l005806@mx1.redhat.com> utrace-devel????????????? ?????2010?8?26-27? ?? ?????2010?8?28-29? ?? ????: ???????????????????????????????? ????: ?????????? ???2,600?/? ??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? --------------------------------------------------------------- ??????: ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????????????????????? ??????: ????????????????????????????????????? ??????????????????????????????????????? ????????????????????????????????????? ============================================================================= ??????: ???????????????? ????????? ??????????????? ???????????? ???????????? ??????????? ???????????? ??????????1/3??3? ????????? ????????????????? ??????????????? ???????????????? ??????????? ???????????? ??????????????? ????????60000?? ????????????? ????????????? ????????????? ?????5S?????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S---? ?5S?????????????? ?5S?????????????? ????????????? ????????? ??????????????? ???????????????????? ???????????? ???????? ??????????????????? ??????????? ???????????????? ????????? ???100%??????????? 100%?????????? ???????????????????? ??????????????? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ??????????????????? ????????????? ??????????????? ????????????????????? ??????????????????? ???????????????????? ??????????????? ?????????????? ???????????????? ??????????????? ?????????????? ?????????????? ????????????? ??????????????? ??????????????? ???????+????????+??? ??????????????????? ============================================================================= ?????????? ??????? ????????? ?MMC?????????? ???????????????(SUMIDA)????????(CASIO)???13?? ??????????????????????????????????????? ?????? ??WF&IE???????????????????????????? ???????????????????????????JIT??????NPS??? ?????????? ??????????????(??,??,??,??,???? ?)??????:??????????ST???????????????????? ??????????????????????????????????????? ??????????????????80?????? ????????????????????????????????????? ????????ABB???????????????-?????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? ??????????????????,?????????????????? ??????????????????????????????????????? ??????? ============================================================================= ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From wrajezxwn7039 at 21cn.com Wed Aug 4 07:07:23 2010 From: wrajezxwn7039 at 21cn.com (wrajezxwn7039 at 21cn.com) Date: Wed, 4 Aug 2010 15:07:23 +0800 (CST) Subject: =?UTF-8?Q?5283_=E6=82=A8=E5=A5=BD=EF=BC=81wexrki872?= Message-ID: <13249538.307351280905643966.JavaMail.root@webmail4> An HTML attachment was scrubbed... URL: From sgty at ghfy.com Wed Aug 4 17:02:08 2010 From: sgty at ghfy.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 5 Aug 2010 01:02:08 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVssr/Dxdb3udy53MDtxNzBpszhyf0=?= Message-ID: <201008041702.o74H20mT012972@mx1.redhat.com> utrace-devel???????????? ?????2010?8?12-13? ?? ?????2010?8?14-15? ?? ?????2010?8?28-29? ?? ?????2200 /?????????????????? ?????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ====================================================================================== ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ??????? ======================================================================================= ???? ??????????????????? ??????????????????????? ????????? ????????????? ??????????????????? ????????????????? ======================================================================================= ???? ???? ?????? ???????????? 1. ???????????? 2. ???????? 3. ???????? 5. ??????????? ?????????? 1. ??????? 2. ?????????? 3. ????????? 4. ????????????? ?????????? ???? ???? ??????????? 1. ?????????? 2. ????SMART?? 3. ?????????? ??????????-??????? ??????????????? 1.?????? 2.?????8??? 3.?????? 4.?????????? 5.??????????????? ??????????????????? ??????????? 1.?????????????????? 2???????????XY?? 2??????????? 2?????????????? 2.??????7???????? 2???? -- ????? 2???? - ????? 2???? - ????? 2???? - ????? 2???? -- ????? 2???? - ????? 2???? - ????? ?????????? ????????????? 1.???????? 2??????????????? 2????????? 2?????????? 2???????? 2??????PDCA???? 2?????????? 2????????????????? 2.???????? 2????? 2????? 2????? 2????? 2????? 2????? 2????? ???? ???? ?????????? 1.???????????????? 2.??????????????????????? 3.???????-?????????????? 4.???? 2?????????????? 2???????????? 2??? 2?????????? 2?????????? 2???????????? 2?????????????? 5.???? 2?????????????? 2???????????? 6.???? 2?????????????? 2???????????? 2???????????????? 2????????????? 7.???? 2??????????????????????????????? 2????????????????????????????? 2????????????????? 2????????????????? 2????????????? ????????? 1.??????? 2?????? --????????????????????????? 2????????????? 2???????????? 2???????????? 2????????????????????? 2.???? 2????????? 2???????????? 2???????????? 2??????????? 2?????????? 2??????????? 2??????????? 2??? 2????????? 2???????? 2??????????????? 3.???? 2???????????????????? 2???????????????? 2??????????????? 2??????????????? 2?????8??? 2????????????? -- ??????12?? ?????? 1.??????????????????? 2.?????????? 3.???????????? 4.????? 5.???????? 6.?????????? 7.?????????? 8.??????? 9.????????? ?? ???????? 1.???????? 2.???7??????? 3.???????? 4.??????????????? 5.???????????? 6.??????????????? 7.?????????? ======================================================================================== ?????????Michael?,????MBA,????PMP????PMP??????, ???????????????????20????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ??????????????????????????? ??????????????????????????????????????? ????????????????????? ------------------------------------------------------------------------------- ???????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From vgnk at xdew.com Wed Aug 4 18:37:21 2010 From: vgnk at xdew.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 5 Aug 2010 02:37:21 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyMPP+srbvqvTorj8t+i/8Q==?= Message-ID: <201008041837.o74IbHeN017332@mx1.redhat.com> utrace-devel????????2?????????? ???????????????????????????????????????????????????????????????????????????? ??????????2010??8??14-15?? ???? ??????????2010??9??18-19?? ???? ??????????2010??9??27-28?? ???? ???????????????????????????????????????????????????????????????????? ??????????2470??/??????2???????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ??????????Judge??????????????????????????????????????????????????Harvard???????????????????? Stanford??????????????.????judge??????????????????????????????????????judge???????????????? ?????????????????????????????????????????????????? ?D?D?D?D?D?D???????????????? 1?????????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????????? 5?????????????????????????????????????????????????????? 6?????????????????????????????????????????? 7?????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????? ??????????????????????10?????? 1???????????????????????????????????? 2?????????????????????????????? 3???????????????????????????????? 4?????????????????????????????? 5???????????????????????????????? 6???????????????????????????????? 7?????????????????????????????? 8?????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????????? ??????????????????9?????????? 1?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2???????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3?????????????????????????? ???????????????????????????????????? 4???????????????????????????? ???????????????????????????????????????????? 5?????????????????????????????????????? ???????????????????????????????????? 6?????????????????????????? ???????????????????????????????????????? 7?????????????????????????????? ?????????????????????????? 8?????????????????????????????????? ?????????????????????????????????????? 9???????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ???????????????????????????????????????? ???????????????????????????????? ?????????????????? B???????????????????????????? 1???????????????????????????? 2?????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????? 7???????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ??????????????????????????????! ???????????????????????????? ???????????????????????????? ???????????????????????????????? ??????3???????? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ??????????????????????9???????? ??????????????????????????5???????? ??????????????????????4???????? ????????????,????????????3??????? ??????????,??????????4??????? ?????????????????????????????????????? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ???????????????????????????????????? ????????????????????4???????? ????????????????6?????? ???????????????????????????????? 2???????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ??????????????6?????????? ?????????????? ???????????????????????? ???????????????????????? ???????????????????????? 1???????????????????????????????????? 2???????????????????????????????????????? 3?????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????? ????????.????????.????????EMBA???????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????? ????????????????????????,??????????????????,?????????????????????????????????? ???????????????????????????????????????????????????????????? ---------------------------------------------------------------------------- ??????????2??????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ?????????????????????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From oleg at redhat.com Wed Aug 4 19:39:35 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 4 Aug 2010 21:39:35 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100803125651.009f0f07@mesquite.lan> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> <20100803122434.GA32698@redhat.com> <20100803131436.GA2185@redhat.com> <20100803125651.009f0f07@mesquite.lan> Message-ID: <20100804193935.GA20294@redhat.com> On 08/03, Kevin Buettner wrote: > > On Tue, 3 Aug 2010 15:14:36 +0200 > Oleg Nesterov wrote: > > > To avoid the unnecessary details, consider the oversimplified example, > > > > $ sleep 10000& > > [1] 2923 > > > > $ cat > SLEEP > > set target-async on > > set non-stop > > target extended-remote :2000 > > file /bin/sleep > > attach 2923 > > info registers > > detach > > ^D > > I'd be curious to know if the behavior improves when you omit > "set target-async on" and "set non-stop". Yes, it works without target-async ;) Oleg. From kevinb at redhat.com Wed Aug 4 23:32:05 2010 From: kevinb at redhat.com (Kevin Buettner) Date: Wed, 4 Aug 2010 16:32:05 -0700 Subject: Q: %Stop && gdb crash In-Reply-To: <20100804193935.GA20294@redhat.com> References: <20100716205147.GA26313@redhat.com> <20100721170400.GA30978@redhat.com> <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> <20100803122434.GA32698@redhat.com> <20100803131436.GA2185@redhat.com> <20100803125651.009f0f07@mesquite.lan> <20100804193935.GA20294@redhat.com> Message-ID: <20100804163205.11c5d7c9@mesquite.lan> On Wed, 4 Aug 2010 21:39:35 +0200 Oleg Nesterov wrote: > > I'd be curious to know if the behavior improves when you omit > > "set target-async on" and "set non-stop". > > Yes, it works without target-async ;) I think that using "set target-async on" is probably very buggy as it is not used very often. (Well, at any rate, I never use it.) I recommend that you avoid it too unless you have some very compelling reason for turning it on. "set non-stop" is probably less buggy in spite of the fact that it's a much more recent addition. (The async stuff has been in GDB since 1999.) Still, I would think that using non-stop will turn up more bugs in gdb than not using it. So, again, I'd suggest avoiding it at least for the early phases of your prototype. At some point, of course, you'll want to turn it on. Kevin From kaishifa61 at 21cn.net Thu Aug 5 00:56:06 2010 From: kaishifa61 at 21cn.net (kaishifa61 at 21cn.net) Date: Thu, 5 Aug 2010 08:56:06 +0800 (HKT) Subject: =?UTF-8?B?5LiO5aWz5Yy755Sf5a6z576e6ICM5r+A5oOF55qE5LiA5aSc5oOFIDg5OQ==?= Message-ID: <27885536.21241280969766565.JavaMail.root@pay3> An HTML attachment was scrubbed... URL: From verona at adanakis.com Thu Aug 5 08:55:25 2010 From: verona at adanakis.com (uwc) Date: Thu, 5 Aug 2010 16:55:25 +0800 Subject: =?gb2312?B?0MJgyM5fvq1gwO253C3A7by8YMTczOFgyf0sL3An?= Message-ID: <20100805165534586552@adanakis.com> ? ? ? ? ? ? ? ? ?! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ? ? ? ? ? ? ? ? ? ? ? ? ? ?.doc Type: application/msword Size: 39424 bytes Desc: not available URL: From mkt at refrimur.com Thu Aug 5 12:49:59 2010 From: mkt at refrimur.com (Refrimur) Date: Thu, 5 Aug 2010 09:49:59 -0300 Subject: Campanha Agosto REFRIMUR 2010 Message-ID: <8d1df1819cb64fece63d3d9300fc20d7@refrimur.com>   Problemas para visualizar a mensagem? Clique aqui.   Caso não deseje mais receber esta Newsletter, Clique Aqui       -------------- next part -------------- An HTML attachment was scrubbed... URL: From rw at 105.winet.cn Thu Aug 5 16:21:18 2010 From: rw at 105.winet.cn (=?GB2312?B?x+vXqs/gudiyv8PF?=) Date: Fri, 6 Aug 2010 00:21:18 +0800 Subject: =?GB2312?B?xvPStcjnus7B9NehusvQxMjLssU=?= Message-ID: <201008051621.o75GKZhW007419@mx1.redhat.com> ???????????--?????? ???????????????? ???????????????? ??????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????2010?8?13-14? ?? ?????2010?8?20-21? ?? ?????2010?8?24-25? ?? ?????2010?9?3-4? ?? ??????????????????????????????????????????HR???????? ? ??4500?/2?/? ???????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ???? ???????????????? ???????????????? ???????????????? ??????????????? ?????????????? ?????????????? ?????????? ????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????? ?????????????????????????????? ???????????????????????????????????? ???????????????????????????? ?? ??,???????????????????????????????????????????????? ????????????,????????????????????????????????? ================================================================================== ???? ?????---???????????,????????????????????????????????? ?????????????? ???????---??????????????????????????? ???????---??????????????????????????????????????????? ??????????????? ???????---??????????????????????????????????????????? ????????????????????????????????????????????????????? ???????---??????????workshop????????????????????????????? ???????????????????? ====================================================================================== ??????? ?????---????????? ???????????????????????????????????????????????????? ????????????????????????????????????????????????????? ???????????????????????????? ??????????????????? ??????????????? ?????????????????????? ???????????????????? ??????????????? ?????????????????????????????? ????????????????????????????????????????95% ?????????????? ??????????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ???????????????????? ?????20?????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????? ?????????????????????????????????????????ESOP????????????????? ???????????????????????????????????????????????????????????? ?????? ??????? ???????????????????????????? ????????????EMAB????????????????4????1? ?????????10???100????????????????????????????????????????????? ?????????????????? ?????????????????????????????????????? ====================================================================================== ????---???? ??? ????????? ???????????? 1????????? 2????????? 3????????? 4????????? 5????????? ???????VS?????????vs????? ????----???????????? 1????? 2???????? 3???????? 4??????? ?????????????????????????? ???????? ????----?????????? 1??"?"???"?"? 2???????????????????? 3???????????????????????????? 4?????? 5?????????????? ?????????????????????????????????? ????----????????? 1???????????????????????? 2????????????? 3?????????????? 4???????????? ??1???????VS ??????? ??2???????????????????????? ????----??????????? 1????????? 2??1%?10% 3?????????? ?????????????????????????????????????????? ?????????? ????----??????? 1? ????vs???? 2? ???????????? 3? ????????? 4? 8???? ???????????????????? ????????????? ??? ?????????? ???????????????? 1??????????????? 2?????7?? ??????????????? 1?TCL???????????? 2????????????? 3?????????? ??????????????? 1? ?????????? 2? ???????? 3? ???????????? 4??????????????? ???????????????? ??? ?????????? 1???????????????? 2??????????????? 3????????????? 4???? ?????????????? 5??????????? ????????????????????? ??? ?????????? 1????????? 2??????????????????? ????????????????????????????????? ??? ??????????? ??????????????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????--????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Thu Aug 5 18:21:32 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 5 Aug 2010 20:21:32 +0200 Subject: Q: %Stop && gdb crash In-Reply-To: <20100804163205.11c5d7c9@mesquite.lan> References: <20100721204203.D040C400B6@magilla.sf.frob.com> <20100723173134.GA29717@redhat.com> <20100726142759.GA17171@redhat.com> <20100728181702.GA26678@redhat.com> <20100802235358.GA9720@host1.dyn.jankratochvil.net> <20100803122434.GA32698@redhat.com> <20100803131436.GA2185@redhat.com> <20100803125651.009f0f07@mesquite.lan> <20100804193935.GA20294@redhat.com> <20100804163205.11c5d7c9@mesquite.lan> Message-ID: <20100805182132.GA28028@redhat.com> Kevin, I am sorry for the delays. I try to avoid reading emails to make the new (heh, initial again ;) all-in-kernel version asap. On 08/04, Kevin Buettner wrote: > > On Wed, 4 Aug 2010 21:39:35 +0200 > Oleg Nesterov wrote: > > > > I'd be curious to know if the behavior improves when you omit > > > "set target-async on" and "set non-stop". > > > > Yes, it works without target-async ;) > > I think that using "set target-async on" is probably very buggy as it > is not used very often. (Well, at any rate, I never use it.) I > recommend that you avoid it too unless you have some very compelling > reason for turning it on. > > "set non-stop" is probably less buggy in spite of the fact that it's a > much more recent addition. (The async stuff has been in GDB since > 1999.) Still, I would think that using non-stop will turn up more bugs > in gdb than not using it. So, again, I'd suggest avoiding it at least > for the early phases of your prototype. At some point, of course, > you'll want to turn it on. Thanks Kevin. I'll try to play with "set non-stop" when I have the new code working. Oleg. From qunishesa at gmail.com Fri Aug 6 02:28:53 2010 From: qunishesa at gmail.com (Seiler Tondreau) Date: Fri, 6 Aug 2010 10:28:53 +0800 Subject: =?GB2312?B?yczO8bK/IDguMTQgvrPE2s3itLTStbDloaLW0NChsOXJz8rQ?= =?GB2312?B?0+vLvcS8ucnIqMja18q437LjttS907vhMjY=?= Message-ID: ??? 8.14 ????????????????????????2678 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ??? 8.14 ????????????????????????.doc Type: application/msword Size: 1051136 bytes Desc: not available URL: From bxj at fret.com Fri Aug 6 05:35:41 2010 From: bxj at fret.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Fri, 6 Aug 2010 13:35:41 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs16jStcPYyunQ0NX+yMvUsby8xNzM4cn9?= Message-ID: <201008060535.o765ZcmZ016558@mx1.redhat.com> utrace-devel???????????????????????????????? ????: 2010??8??7-8?? ?????????? ??????2010??8??14-15?? ?????????? ??????2010??10??16-17?? ?????????? ??????????2500/???????????????????????????????????? ?????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ????????????????????????????chinammc2010 at 126.com?????? ======================================================================================== ???????????????????? 1.?????????????????????????????????????????????????????????????????????? 2.???????????????????????????????????????? 3.???????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? 5.?????????????????????????????????????????????? 6.?????????????????????????? 7.?????????????????????????????????????????? 8.???????????????????????????????????????????????????????? 9.???????????????????????????????????????????? 10.???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? =========================================================================================== ????????: ???????? ????/?????????????? 1.????/???????? 2.????????/???????????????? 3.????????/?????????????????????????? 4.????????/???????????????????????? 5.???????????????????????D?D?????????????????? 6.???????????????????????????? 7.?????????????????????????????????????????? 8.????/?????????????????? 9.???????????????????????????????????????????? ???????? ????????/?????????????? 1.????/?????????????????D?D????????????????/????/???????? 2.?????????????????????? 3.?????????????????????????????????????????????????? 4.????????????????????PDP??????NLP???? 5.????????????????????????????5W1H?????????? 6.?????????????????????????? 7.???????????????? 8.???????????????????????????????????????????????????????????????? ???????? ????????5S???? 1.5S?????? 2.???????????????????????? 3.???????????????????????? 4.???????????????????????? 5.???????????????????????? 6.???????????????????????????? ???????????????? 1.??????????5?????? 2.???????????????????????????? 3.?????????????????? 4.???????????????????????????????? 5.???????????????????????????????????????????????????????? 6.?????????????????????????????????????????????? 7.?????????????????????????? ?????????????????????????? 1.???????????????????????????? 2.PDCA?????????????????????????? 3.????SMAC???????????????????? 4.??????????/????/?????????????????????? 5.???????????????????????????????????????????????????????? ?????????????????????????????????? 1.?????????????? 2.?????????????? 3.?????????????????????????????????? 4.?????????????????? 5.????????????????????12?????? 6.?????????????????? 7.???????? 8.???????????????????????????????? ???????????????? 1.???????????????? 2.?????????????????? 3.?????????????????? 4.?????????????????? 5.?????????????????? 6.?????????????????? 7.?????????????????? ?????????????????????????????? 1.???????? 2.?????????? 3.?????????????????? ???????????????????? 1.?????????????????????????????? 2.?????????????? ???????????????????????????????????????????????????????????????? ??????????????????????????????/????/?????????????????????????????????????? 3.?????????????????????????????? ?????????????????????????????????????????????? ========================================================================================== ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????5????????????500?????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????TTT???????????????? ??????????????????????????/???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????TCL?? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? =========================================================================================== ??????????/????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From utrace-devel at redhat.com Fri Aug 6 11:28:59 2010 From: utrace-devel at redhat.com (utrace-devel at redhat.com) Date: Fri, 6 Aug 2010 07:28:59 -0400 Subject: utrace-devel@redhat.com 57% OFF on Pfizer! Message-ID: <201008061129.o76BSxgR008168@mx1.redhat.com> http://groups.yahoo.com/group/bondiharlacherl/message ienst war es langte wirklich kaum zum Leben, so gut war es aber fur meinen erwahlten Beruf. Nun war ich nicht mehr wie fruher des Abends nach der Ruckkehr von der Arbeitss From loytzi_dora at hotmail.com Fri Aug 6 17:06:07 2010 From: loytzi_dora at hotmail.com (dora lou) Date: Fri, 6 Aug 2010 17:06:07 +0000 Subject: =?gb2312?B?ztLSqrDRy/zLtbP2wLSjrLK7yLs=?= =?gb2312?B?ztLSqrfowcujoTMxcg==?= Message-ID: ?????????????? ?????????????????? ?????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????~??????? ?????????????????????? ?????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? ?????????????????????????????????????????????? ??????????????????????????????10?????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????? 1. ????????????????????????????????????????=?????????????? ????28000?? 2. ??????????????????????????????????CEO?????????????? ????15800?? 3. ??????????????????????????????????????????????DVD ????29800?? 4. ???????????????????????????????????????????????????????? ????2980?? 5. ????????????????????????????.???????????????????????????????????? 6. ????????????????????????????.????08??09?????????????? ????38000?? 7. ?????????????????????????? ???????????????????? ???????????? 8. ???????????????????????????????????????????????? 9. ???????????????????????????????????????????? ????22000?? 10.?????????????????????????????????? ??????DVD ????22000?? PS?????????????? ?????????????? ???????????????????????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From whinstone at hornaments.com Fri Aug 6 20:47:51 2010 From: whinstone at hornaments.com (Fulbright Carrion) Date: Fri, 06 Aug 2010 22:47:51 +0200 Subject: Your private photo attached Message-ID: <4C5C72AB.2020204@hornaments.com> Your private photo attached -------------- next part -------------- A non-text attachment was scrubbed... Name: selflessness.zip Type: application/octet-stream Size: 11205 bytes Desc: not available URL: From kaishifa101 at 21cn.net Fri Aug 6 23:53:40 2010 From: kaishifa101 at 21cn.net (kaishifa101 at 21cn.net) Date: Sat, 7 Aug 2010 07:53:40 +0800 (CST) Subject: =?UTF-8?B?4oCc5omT6YeO5oiY4oCd5pyJ5aSa6L+H55i+77yfIDczMw==?= Message-ID: <12358578.14821281138820840.JavaMail.root@pay1> An HTML attachment was scrubbed... URL: From xcy at wqeg.com Sat Aug 7 05:30:55 2010 From: xcy at wqeg.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Sat, 7 Aug 2010 13:30:55 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs1tDQocbz0rW0tNK1sOXJz8rQ0+u5yciovKTA+A==?= Message-ID: <201008070530.o775UHL1023440@mx1.redhat.com> utrace-devel????????????????????? ?????2010?8?19-22? ?? ?????2010?8?26-29? ?? ????????????????????????????? ??????????????????????????????????????????????????? ???8000?/????????????????????????????????4500?/? ???? 1??????????????????????????????????????????????????????????? 2??????????????????????? 3??????????????????????? 4???????????????????????????????? 5?????????????????? ???? 1????????????????????????????????????? 2?????????????????????????????????????????2-3????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ?????2009?10?23????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????????????????? -------------------------------------------------------------------------------------- ???? 1??????????????????????????????????????????????? ?????????????????????? 2???????????????????????????????????????????????? ??????????????????????????????????????????????????????????? 3??????????-------?????????????????????????????????? ???????????????????????????? 4????????---?????????????????????????????????????? ???????????????????? 5?????????---????????????????????????????????????? ??????????????????????????????????????? 6?????????---????????????????????????????????????? ????????????????????????????????????????????????? ???????????? 7???????-----??????????????????????????????? -------------------------------------------------------------------------------------------- ???? 1???????????????????????????????????????????????????????????????? 2?????????????????????????????????????? 3???????????????????????? 4?????????????????????????????????????????? 5????????????????????????????????? 6???????????????????????????????? 7?????????????????????????? ????????????????????????????,???????????????????? ????????????????????????????????????? --------------------------------------------------------------------------------------------------------------- ???? ??????????????????????? ????????? ??1??? ------?????????? ??2?????------???????????????? ??3?????-------??????????????? ??4????????-------???????????????????? ??5???????------??????????????? ??6?????------????????????? ??7??????------?????????????????? ??8????????------?????????????????? ??9??????------??MBO???? ??10?????-------A???????????? ??11?????? ??12???????????????? ????????????? 2.1 XXX??????????????????????????????????? 2.2 ????????----????????? 2.3 ????????? 2.4 ?????? 2.5 ??????????? 2.6 ?????????????????? 2.7 ??????????? 2.8 ???????????? 2.9 ??????????? 2.10 ??????????? 2.11 ?????? ????????????? 3.1 ???????? 3.2 ??????????? 3.3 ????? 3.4 ?????? 3.5 ???????? ???????XXX???????????????????? ?????????????????? 4.1????????? 1???????????? 2??????? 3??????? 4???????? 5??????????? 4.2???????????? 1?????????? 2?????????? 3?????????? 4.3 ?????????? ?????????????????? 5.1 ????????? 5.2 ????????? 5.3 ???? ????????? ??????????????????????????? ????????? ?? ????????? ? ???????????? ? ???? ? ?????? ? ???? ????????????????? ??????????????? ? ?????? ? ?????? ? ??????? ???????????? ? ??????????? ? ??????????? ? ?????????? ? ???????????? ? ????????????? ? ????????????? ????????? ??????? ?? ?????????? ??????????? ? ?????????????? ? ????????? ? ????????? ? ???????? ? ????????? ? ??????????? ? ??????????? ? ???????? ? ??????????????? ??23??? ????????????? ???????????? ?????????????????????? ???????????????? ??????????? ?????????????? ????????? ???????????? ?????????????????? ??????????????? ???????????????? ???????????? ?????? ??????????? ????????? ??????????? ??????????????? ---------------------------------------------------------------------------------------------- ???????? ?????????Z???????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????,???????????????????? ??????????? ????? ??????????????????????????????????????? ????? ??????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????? ---------------------------------------------------------------------------------------------- ????????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From cornel at upload-ro.ro Sat Aug 7 07:29:07 2010 From: cornel at upload-ro.ro (oferta cursuri de perfectionare) Date: Sat, 7 Aug 2010 10:29:07 +0300 Subject: oferta cursuri de perfectionare Message-ID: <20100806.WFKKPNDBQZLXFJIS@upload-ro.ro> An HTML attachment was scrubbed... URL: From lunangelykyta at hotmail.com Sat Aug 7 10:57:13 2010 From: lunangelykyta at hotmail.com (=?gb2312?B?RGVuaXNlIEFuZ6imbGljYSBPbGl2YXMgUGF6?=) Date: Sat, 7 Aug 2010 03:57:13 -0700 Subject: =?gb2312?B?udjT2tXiuPayu86qyMvWqrXEw9g=?= =?gb2312?B?w9yjoTg2eg==?= Message-ID: ?????? ????????? ?????????M???????????300%???700%? ?????????W??????????? ?48?????????????A m?????????????????T?????? ??????L????????????????T?????????????????F? ????? ???????D????????? 1.???????L??? ????? 2.???24???E10???? ????? 3.?????K???50?????? ????? ?????????????8????????????Q????????????? ?????I?? ps??????????????????????O????? ????????????E??????Y-??17??K???? ????????????O?????????A% -------------- next part -------------- An HTML attachment was scrubbed... URL: From shangxin33 at 21cn.net Sun Aug 8 05:15:37 2010 From: shangxin33 at 21cn.net (shangxin33 at 21cn.net) Date: Sun, 8 Aug 2010 13:15:37 +0800 (HKT) Subject: =?UTF-8?B?5rWL5rWL5L2g5L+p5oCn54ix6KGA5Z6L6YWN5LiN6YWN77yf?= =?UTF-8?B?LOS4jeS7lue7j+inguaIkeWug+WwhueahOmXtOW/g+WboA==?= Message-ID: <27727622.22321281244537230.JavaMail.root@pay3> An HTML attachment was scrubbed... URL: From lords31 at hotmail.com Sun Aug 8 14:43:11 2010 From: lords31 at hotmail.com (carlos plaza ros) Date: Sun, 8 Aug 2010 14:43:11 +0000 Subject: =?gb2312?B?MjAxMMrAsqm74bXEMjM=?= =?gb2312?B?uPbD1szstPO70TA0Zw==?= Message-ID: ?????? ???????? ??????????????????????????e?????????????????P?????????????????????????? ?????????? ???????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????? ???????I??????????????????????????????????????????? ???????????????????????????? ???????h?????????e?????????????????? ???????? ????? ??????????????? 1. ???????????????????=??????? ??28000? 2. ??????Y???????????CEO??????? ??15800? 3. ????????????a???????????DVD ??29800? 4. ?????????????????????????? ??2980? 5. ?????????????.?????????????????? 6. ??????????????.??08?09??????? ??38000? 7. ????????????? ?????????? ??e???? 8. ?????????????k??????????? 9. ?????P????????????????? ??22000? 10.????????????????? ???DVD ??22000? PS??????? ??????? ??????????3?????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From elmer at deguia.net Mon Aug 9 03:24:03 2010 From: elmer at deguia.net (Virgil Quint) Date: Mon, 09 Aug 2010 12:24:03 +0900 Subject: Your private photo attached Message-ID: <4C5F7257.7060605@deguia.net> Your private photo attached -------------- next part -------------- A non-text attachment was scrubbed... Name: afreet.zip Type: application/octet-stream Size: 12354 bytes Desc: not available URL: From nickmaxx62 at yahoo.in Mon Aug 9 07:58:11 2010 From: nickmaxx62 at yahoo.in (Nick Maxx) Date: Mon, 9 Aug 2010 13:28:11 +0530 (IST) Subject: ($950.000.00) Message-ID: <952658.98896.qm@web95605.mail.in.yahoo.com> Please my dear, I have been waiting for you since to contact me for your Conformable Cheque value of $950.000.00 United States Dollars, but I did not hear from you since that time. Then I went and convicted it to ATM CARD with Service ABA Bank, before I travel out of the country for a 3 Months Course. ? What you have to do now is to contact the Service ABA Bank as soon as possible to know when they will deliver your package to you because of the expiring date. For your information, I have paid for the delivering Charge, Insurance premium and Clearance Certificate Fee of the ATM CARD showing that it is not a Drug Money or meant to sponsor Terrorist attack in your Country. ? The only money you will send to the DIPLOMATIC COURIER SERVICE to deliver your Atm Card ?direct to your postal Address in your country is ($105.00 US) Dollars only being Security Keeping Fee of the Courier Company so far.Again, don't be deceived by anybody to pay any other money except $105.00US Dollars. I would have paid that but they said no because they don't know when you will contact them and in case of demur rage. You have to contact the DIPLOMATIC COURIER SERVICE now for the delivery of your Atm Card with this information bellow:- ? Contact Person: (Director Briefing Steve Cocheo) Email Address: (abatrust at w.cn) Telephonenumber:( +2348165539710) ?????????????????????????????? ? Finally, make sure that you reconfirm your Full Name, Postal address and Direct telephone number to them again to avoid any mistake on the Delivery and also send to them Security Keeping Fee of $105.00US Dollars,then ask them to give you the tracking number to enable you track your package over there and know when it will get to your address. ? Let me repeat again, try to contact them as soon as you receive this mail to avoid any further delay and remember to pay them their Security Keeping fee of $105.00 US Dollars for their immediate action. You should also let me know through email as soon as you receive your ATM CARD . ? Yours Faithfully, Mr. Mr. Nick Maxx. -------------- next part -------------- An HTML attachment was scrubbed... URL: From be at zy.com Mon Aug 9 14:06:35 2010 From: be at zy.com (=?GB2312?B?xeDRtQ==?=) Date: Mon, 09 Aug 2010 14:06:35 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyfqy+s/Ws6HOo7v61KS3wNPrv9jWxg==?= Message-ID: <201008091406.o79E68YB008197@mx1.redhat.com> utrace-devel????????????? ?????2010?8?26-27? ?? ?????2010?8?28-29? ?? ????: ???????????????????????????????? ????: ?????????? ???2,600?/? ??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? --------------------------------------------------------------- ??????: ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????????????????????? ??????: ????????????????????????????????????? ??????????????????????????????????????? ????????????????????????????????????? ============================================================================= ??????: ???????????????? ????????? ??????????????? ???????????? ???????????? ??????????? ???????????? ??????????1/3??3? ????????? ????????????????? ??????????????? ???????????????? ??????????? ???????????? ??????????????? ????????60000?? ????????????? ????????????? ????????????? ?????5S?????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S---? ?5S?????????????? ?5S?????????????? ????????????? ????????? ??????????????? ???????????????????? ???????????? ???????? ??????????????????? ??????????? ???????????????? ????????? ???100%??????????? 100%?????????? ???????????????????? ??????????????? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ??????????????????? ????????????? ??????????????? ????????????????????? ??????????????????? ???????????????????? ??????????????? ?????????????? ???????????????? ??????????????? ?????????????? ?????????????? ????????????? ??????????????? ??????????????? ???????+????????+??? ??????????????????? ============================================================================= ?????????? ??????? ????????? ?MMC?????????? ???????????????(SUMIDA)????????(CASIO)???13?? ??????????????????????????????????????? ?????? ??WF&IE???????????????????????????? ???????????????????????????JIT??????NPS??? ?????????? ??????????????(??,??,??,??,???? ?)??????:??????????ST???????????????????? ??????????????????????????????????????? ??????????????????80?????? ????????????????????????????????????? ????????ABB???????????????-?????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? ??????????????????,?????????????????? ??????????????????????????????????????? ??????? ============================================================================= ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From sj at wu.com Mon Aug 9 20:30:13 2010 From: sj at wu.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Tue, 10 Aug 2010 04:30:13 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsvbW1zbLJubqzybG+vLC5qdOmyczMuMXQ?= Message-ID: <201008092030.o79KUGJk008523@mx1.redhat.com> utrace-devel?????????????? ?????2010?8?24-25? ?? ?????2010?9?4-5? ?? ?????2010?9?7-8? ?? ?????2010?10?9-10? ?? ?????????2500?/?????????????????? ????? ?????????????????????????????????. ???????600?/?;??800?/?(??????????????) ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ????? ?????????????????????? ????????????????????????????? ?????????????? ???????????????? ????????????? ??????????? ------------------------------------- ????? ?????????????? ????????????? ??????????? ????????????????? ??????????????? ??????????????? ?????????? ?????????? ????????? ------------------------------------- ???? ?????????????????? ??????????????? ?????KPI?????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ????????????? ????????????? ???? ?????? ?????? ???? ??????????????? ??????????????? XX??2009?????? ??????????? ?????????? ?????????????? ?????????? ????????????????? ????????????? ??????? ????????????? ???????????? ??????????? ??????????????? ?????????????? ???????????? ????????? ????????? ??????? ?????????????????? ??????????? ?????-??????? ????? ????????????? ?????????? ??????? ?????????????? ?????????? ??????????? ??????????????? ?????????? ????????(???)???? ???????????? ????????????? ?????????? ?????????? ??????? ?????? ??????????? ??????????????????? ??????? ?????????????? ????? ??????????????? ?????? ???????????????? ????????????? ?????????? ?????????????? ??????????? ???????????????? ??????????? ??????????? ?????????????? ??????????????? ?????????????????? ??????????? ??????????? ??????? ?????????????? ???? ???? ??????? ?????????? ???????? ??????????? ???????? ??????? ?????????? ????????? ?????????????? ??(??)??????? ???????????? ??????????? ????????? ???????? ?????????? ????????? ???????????????? ??????????? ???????????? ?????? ??????? ?????????? ???????? ????????? ????? ???????????? ????????????????????? ???????????? ??????? ?????????? ???????????? ??????????? ???????????? ????????? ?????????? ?????????????? ??????????? ????? ???????? ???? ?????????? ???????? ???????? ??????? ??????????????? ????????????? ??????????? ???????? ??????????? ?????????????????? ??????????????? ?????KPI?????? ??????????? ?????????????? ???????? ????? ???????????????? ?????? ????????????????? ??????????? ??????????? ????????????? ???Pareto(???)??? ABC??? ???????????????? ??????????????? ??????????????? ????????????? ????????????ff ?????????? ???????? ????????????? ?????????????? ?????????????? ????????VMI?? ???JIT???? ???????????? ??????? ???JIT? JIT?JIC??? JIT?????JIT??????? ?????????? ???????????? ??????? (VMI) ?????? ?????? ------------------------------------------------------------------------------ ??????????? 1986????Gerber?????????Michigan State University (???????) ????????????,?????Heinz(??)??????????????????????????? ?????????????????????????????2000???,???????????????? ?????????,???????500??????????????,?????????????????? ??????????????????????????????????????????????????? ??????????? ??????????????????????????????????????? ?????????????????????????????????????????????????? ????? ?????????????,?????????,??,???????????,?????,?? ???????????????????????????????,??????????????,???? ????????????????? ---------------------------------------------------------------------------------------------- ????? ????????????020-62351156 ??????? ????? 2010?___________ ? ______ ??? ??????????????? ??????????????????????????????????????????? ??????????????? ?????????????? ????????????? ????????????????? ??????????????????????? ????????? ? ??????????? ? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? From sj at wy.com Tue Aug 10 04:05:42 2010 From: sj at wy.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Tue, 10 Aug 2010 04:05:42 -0000 Subject: =?GB2312?B?QjZ1dHJhY2UtZGV2ZWzIw8/6ytu+q9OiuPy36L/x?= Message-ID: <201008100405.o7A45FZA005241@mx1.redhat.com> utrace-devel????????2?????????? ???????????????????????????????????????????????????????????????????????????? ??????????2010??8??14-15?? ???? ??????????2010??9??18-19?? ???? ??????????2010??9??27-28?? ???? ???????????????????????????????????????????????????????????????????? ??????????2470??/??????2???????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ??????????Judge??????????????????????????????????????????????????Harvard???????????????????? Stanford??????????????.????judge??????????????????????????????????????judge???????????????? ?????????????????????????????????????????????????? ?D?D?D?D?D?D???????????????? 1?????????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????????? 5?????????????????????????????????????????????????????? 6?????????????????????????????????????????? 7?????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????? ??????????????????????10?????? 1???????????????????????????????????? 2?????????????????????????????? 3???????????????????????????????? 4?????????????????????????????? 5???????????????????????????????? 6???????????????????????????????? 7?????????????????????????????? 8?????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????????? ??????????????????9?????????? 1?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2???????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3?????????????????????????? ???????????????????????????????????? 4???????????????????????????? ???????????????????????????????????????????? 5?????????????????????????????????????? ???????????????????????????????????? 6?????????????????????????? ???????????????????????????????????????? 7?????????????????????????????? ?????????????????????????? 8?????????????????????????????????? ?????????????????????????????????????? 9???????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ???????????????????????????????????????? ???????????????????????????????? ?????????????????? B???????????????????????????? 1???????????????????????????? 2?????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????? 7???????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ??????????????????????????????! ???????????????????????????? ???????????????????????????? ???????????????????????????????? ??????3???????? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ??????????????????????9???????? ??????????????????????????5???????? ??????????????????????4???????? ????????????,????????????3??????? ??????????,??????????4??????? ?????????????????????????????????????? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ???????????????????????????????????? ????????????????????4???????? ????????????????6?????? ???????????????????????????????? 2???????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ??????????????6?????????? ?????????????? ???????????????????????? ???????????????????????? ???????????????????????? 1???????????????????????????????????? 2???????????????????????????????????????? 3?????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????? ????????.????????.????????EMBA???????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????? ????????????????????????,??????????????????,?????????????????????????????????? ???????????????????????????????????????????????????????????? ---------------------------------------------------------------------------- ??????????2??????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ?????????????????????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From xxhaqg at vip.163.com Tue Aug 10 17:33:18 2010 From: xxhaqg at vip.163.com (2010-08-11 01:33:21) Date: Wed, 11 Aug 2010 01:33:18 +0800 Subject: =?utf-8?B?6YKu5Lu26JCl6ZSA77yBNuS6v+mCruS7tuaVsOaNrue7neWvhuWkp+WFrOW8gO+8ge+8gQ==?= Message-ID: ???????????????6??????????????6???????????????????????6???,????? %{LIST_MA-RO5}= ??????????????,??????????????????????????????????????????????????????????????????????????????????????????????????????? %{L[IST[_;MA<>;RO5} ?????????????????????????????????? ?6??????????????????????????????????????????????126,163,???????????? 6???????100????,????280M???????????????????? ??????QQ--55480,0438?6???,?????QQ????? 6???????????????,??? ???????,??,???? 100%???????,????????? ???????,??? ??QQ--554,800438?6????,?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From news at maisservicos.com Wed Aug 11 18:31:46 2010 From: news at maisservicos.com (Partners Finances) Date: Wed, 11 Aug 2010 19:31:46 +0100 Subject: Reduza as mensalidades de seus creditos ate -60% Message-ID: <20100811183156.86E2C1DB8D7@server7.nortenet.pt> Autoriza??o : Autorizo(amos) que os dados facultados sejam tratados informaticamente pela M.B. FINANCES, S.A., PARTNERS FINANCES, intermedi?rio em opera??es de cr?dito, para efeitos de prospec??o comercial. Fica-me(nos) reservado o direito de acesso ? informa??o, de correc??o, aditamento ou elimina??o dos meus(nossos) dados pessoais, mediante contacto escrito para : M.B. FINANCES, S.A., PARTNERS FINANCES, EDIF. D.PEDRO I, PISO 2, QUINTA DA FONTE, 2770-071 PA?O D'ARCOS. NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Para deixar de receber estas ofertas no seu e-mail clicar aqui -------------- next part -------------- An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Wed Aug 11 22:37:50 2010 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Wed, 11 Aug 2010 19:37:50 -0300 Subject: Mega Promocoes de Eletronicos Aproveite Message-ID: <3971e130553a7a218c841af900179c89@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Aug 11 23:58:10 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Aug 2010 01:58:10 +0200 Subject: gdbstub initial code, v3 Message-ID: <20100811235810.GA9783@redhat.com> Please see the attached ugdb.c. It supports multiple inferiors/threads, stop/cont, clone/exit. It doesn't report W/X when the process exits yet, but this is only because I'd like to discuss the current problems with the exited leader first, then implement this as a separate change. Any code review is very much appreciated. Problems: - It doesn't support all-stop mode. Please tell me if this is needed. I hope not, this needs a lot of nasty complications :/ - We should discuss utrace limitations: UTRACE_RESUME races/problems, utrace_prepare_examine() issues. - I just finished this code, and it doesn't work with gdb ;) I will investigate tomorrow, but I am almost sure gdb is wrong. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { // XXX: temporary racy check WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ struct ugdb_thread { int t_tid; int t_stop_state; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; // create/attach border struct utrace_engine *t_engine; }; static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static inline void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); ugdb_del_stopped(ugdb, thread); spin_unlock(&ugdb->u_slock); } list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH)); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static void ugdb_detach_thread(struct ugdb_thread *thread, bool can_wait) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); if (ret == -EINPROGRESS) { if (WARN_ON(!can_wait)) goto put; utrace_barrier_pid(thread->t_spid, thread->t_engine); } put: utrace_engine_put(thread->t_engine); /* to catch use-after-free */ thread->t_engine = NULL; } static const struct utrace_engine_ops ugdb_utrace_ops; /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; thread->t_engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(thread->t_engine)) goto free_thread; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state = P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb->u_cur_tinfo = NULL; } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct ugdb_thread *ugdb_attach_main(struct ugdb *ugdb, struct ugdb_process *process) { struct ugdb_thread *thread; struct pid *spid; spid = find_get_pid(process->p_pid); if (!spid) return NULL; thread = ugdb_attach_thread(process, spid); if (IS_ERR(thread)) thread = NULL; put_pid(spid); return thread; } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct pid *next = NULL; task = pid_task(curr, PIDTYPE_PID); BUG_ON(!task); spin_lock_irq(&task->sighand->siglock); for (;;) { task = next_thread(task); // XXX: BUG: if main is not group leader we can race with exec if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&task->sighand->siglock); return next; } static int ugdb_attach(struct ugdb *ugdb, int pid) { struct ugdb_process *process; struct ugdb_thread *thread; struct pid *main_pid, *curr_pid; // XXX: check if exists process = ugdb_create_process(ugdb, pid); if (!process) goto err; mutex_lock(&ugdb->u_mutex); // XXX: check if group leader ? thread = ugdb_attach_main(ugdb, process); if (!thread) goto abort; main_pid = thread->t_spid; curr_pid = main_pid; for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } // XXX mark it just attached mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); ugdb_destroy_process(process); err: return -1; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_cur_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); WARN_ON(thread->t_stop_state & T_STOP_ACK); if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; ret = true; thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } unlock: spin_unlock(&ugdb->u_slock); return ret; } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { /* * (gdb) interrupt & * (gbd) interrupt -a & * * make sure -a actually works if it races with clone. */ if (all && !(thread->t_stop_state & T_STOP_ALL)) { /* * We hold ugdb->u_mutex, so we can't race with * ugdb_report_clone(). But we need spinlock to * avoid the race with ugdb_add_stopped() which * can change ->t_stop_state in parallel. */ spin_lock(&ugdb->u_slock); thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); } return 0; } // XXX: currently we can do this lockless ... thread->t_stop_state = all ? (T_STOP_REQ | T_STOP_ALL) : T_STOP_REQ; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state == T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; bool is_main; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_cur_tinfo(ugdb); is_main = (process->p_pid == thread->t_tid); ugdb_destroy_thread(thread); if (is_main) ; // XXX: DAMN!!! unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; const char *stop = "T00"; int pid, tid; int ret = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; pid = thread->t_process->p_pid; tid = thread->t_tid; ret = 1; unlock: mutex_unlock(&ugdb->u_mutex); if (ret) { struct pbuf *pb = &ugdb->u_pbuf; if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } pb_printf(pb, "%sthread:p%x.%x;", stop, pid, tid); pb_end(pb); } return ret; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_cur_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; task = thread_to_task(thread); for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_cur_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_stop(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, 0, tid); if (!thread) return -ESRCH; return ugdb_stop_thread(thread, false); } static int xxx_cont(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, 0, tid); if (!thread) return -ESRCH; return ugdb_cont_thread(thread, true); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } count = pb_copy_to_user(pb, ubuf, count); if (count > 0) *ppos += count; return count; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); *ppos += count; return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Thu Aug 12 01:11:13 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Aug 2010 03:11:13 +0200 Subject: gdbstub initial code, v3 In-Reply-To: <20100811235810.GA9783@redhat.com> References: <20100811235810.GA9783@redhat.com> Message-ID: <20100812011113.GA13212@redhat.com> On 08/12, Oleg Nesterov wrote: > > Problems: > > - It doesn't support all-stop mode. > > Please tell me if this is needed. I hope not, this needs > a lot of nasty complications :/ > > - We should discuss utrace limitations: UTRACE_RESUME > races/problems, utrace_prepare_examine() issues. > > - I just finished this code, and it doesn't work with gdb ;) Noticed the typo in ugdb.c, it needs this one-liner fix: --- x/ugdb.c +++ x/ugdb.c @@ -603,7 +603,7 @@ static int ugdb_cont_thread(struct ugdb_ ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread - WARN_ON(!all && !(thread->t_stop_state == T_STOP_STOPPED)); + WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; I attached the patched ugdb.c. > I will investigate tomorrow, but I am almost sure gdb is > wrong. Yes, this seems to be true... Tomorrow. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { // XXX: temporary racy check WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ struct ugdb_thread { int t_tid; int t_stop_state; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; // create/attach border struct utrace_engine *t_engine; }; static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static inline void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); ugdb_del_stopped(ugdb, thread); spin_unlock(&ugdb->u_slock); } list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH)); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static void ugdb_detach_thread(struct ugdb_thread *thread, bool can_wait) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); if (ret == -EINPROGRESS) { if (WARN_ON(!can_wait)) goto put; utrace_barrier_pid(thread->t_spid, thread->t_engine); } put: utrace_engine_put(thread->t_engine); /* to catch use-after-free */ thread->t_engine = NULL; } static const struct utrace_engine_ops ugdb_utrace_ops; /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; thread->t_engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(thread->t_engine)) goto free_thread; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state = P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb->u_cur_tinfo = NULL; } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct ugdb_thread *ugdb_attach_main(struct ugdb *ugdb, struct ugdb_process *process) { struct ugdb_thread *thread; struct pid *spid; spid = find_get_pid(process->p_pid); if (!spid) return NULL; thread = ugdb_attach_thread(process, spid); if (IS_ERR(thread)) thread = NULL; put_pid(spid); return thread; } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct pid *next = NULL; task = pid_task(curr, PIDTYPE_PID); BUG_ON(!task); spin_lock_irq(&task->sighand->siglock); for (;;) { task = next_thread(task); // XXX: BUG: if main is not group leader we can race with exec if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&task->sighand->siglock); return next; } static int ugdb_attach(struct ugdb *ugdb, int pid) { struct ugdb_process *process; struct ugdb_thread *thread; struct pid *main_pid, *curr_pid; // XXX: check if exists process = ugdb_create_process(ugdb, pid); if (!process) goto err; mutex_lock(&ugdb->u_mutex); // XXX: check if group leader ? thread = ugdb_attach_main(ugdb, process); if (!thread) goto abort; main_pid = thread->t_spid; curr_pid = main_pid; for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } // XXX mark it just attached mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); ugdb_destroy_process(process); err: return -1; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_cur_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); WARN_ON(thread->t_stop_state & T_STOP_ACK); if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; ret = true; thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } unlock: spin_unlock(&ugdb->u_slock); return ret; } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { /* * (gdb) interrupt & * (gbd) interrupt -a & * * make sure -a actually works if it races with clone. */ if (all && !(thread->t_stop_state & T_STOP_ALL)) { /* * We hold ugdb->u_mutex, so we can't race with * ugdb_report_clone(). But we need spinlock to * avoid the race with ugdb_add_stopped() which * can change ->t_stop_state in parallel. */ spin_lock(&ugdb->u_slock); thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); } return 0; } // XXX: currently we can do this lockless ... thread->t_stop_state = all ? (T_STOP_REQ | T_STOP_ALL) : T_STOP_REQ; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; bool is_main; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_cur_tinfo(ugdb); is_main = (process->p_pid == thread->t_tid); ugdb_destroy_thread(thread); if (is_main) ; // XXX: DAMN!!! unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; const char *stop = "T00"; int pid, tid; int ret = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; pid = thread->t_process->p_pid; tid = thread->t_tid; ret = 1; unlock: mutex_unlock(&ugdb->u_mutex); if (ret) { struct pbuf *pb = &ugdb->u_pbuf; if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } pb_printf(pb, "%sthread:p%x.%x;", stop, pid, tid); pb_end(pb); } return ret; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_cur_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; task = thread_to_task(thread); for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_cur_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_stop(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, 0, tid); if (!thread) return -ESRCH; return ugdb_stop_thread(thread, false); } static int xxx_cont(struct ugdb *ugdb, int tid) { struct ugdb_thread *thread = ugdb_find_thread(ugdb, 0, tid); if (!thread) return -ESRCH; return ugdb_cont_thread(thread, true); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } count = pb_copy_to_user(pb, ubuf, count); if (count > 0) *ppos += count; return count; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); *ppos += count; return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Thu Aug 12 02:37:50 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Aug 2010 04:37:50 +0200 Subject: gdbstub initial code, v3 In-Reply-To: <20100812011113.GA13212@redhat.com> References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> Message-ID: <20100812023750.GA17011@redhat.com> On 08/12, Oleg Nesterov wrote: > > > I will investigate tomorrow, but I am almost sure gdb is > > wrong. > > Yes, this seems to be true... Tomorrow. Can't sleep because of this problem ;) So, the patch below fixes the problem, and gdb + /proc/ugdb seems to work. Indeed, gdb sees that this fd is not pipe/tcp and uses the "hardwire" serial_ops, but hardwire_readchar() doesn't play well with select(). Please teach gdb to use poll/select ? Oleg. --- gdb-7.1/gdb/ser-unix.c +++ gdb-7.1/gdb/ser-unix.c @@ -452,7 +452,7 @@ hardwire_raw (struct serial *scb) static int wait_for (struct serial *scb, int timeout) { -#ifdef HAVE_SGTTY +#if 1 while (1) { struct timeval tv; @@ -474,13 +474,14 @@ wait_for (struct serial *scb, int timeou else numfds = gdb_select (scb->fd + 1, &readfds, 0, 0, 0); - if (numfds <= 0) + if (numfds <= 0) { if (numfds == 0) return SERIAL_TIMEOUT; else if (errno == EINTR) continue; else return SERIAL_ERROR; /* Got an error from select or poll */ + } return 0; } From tromey at redhat.com Thu Aug 12 04:37:37 2010 From: tromey at redhat.com (Tom Tromey) Date: Wed, 11 Aug 2010 22:37:37 -0600 Subject: gdbstub initial code, v3 In-Reply-To: <20100812023750.GA17011@redhat.com> (Oleg Nesterov's message of "Thu, 12 Aug 2010 04:37:50 +0200") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> Message-ID: >>>>> "Oleg" == Oleg Nesterov writes: Oleg> So, the patch below fixes the problem, and gdb + /proc/ugdb seems Oleg> to work. Oleg> Indeed, gdb sees that this fd is not pipe/tcp and uses the "hardwire" Oleg> serial_ops, but hardwire_readchar() doesn't play well with select(). Oleg> Please teach gdb to use poll/select ? I looked at this a little bit. It seems to me that the "hardwire" stuff is for talking to ttys, and we instead want gdb to be using the pipe code. Maybe a little hack to stat the open_name in the hardwire case (in serial_open) would be appropriate. Tom From mercadal_diaz_ana at hotmail.com Thu Aug 12 05:21:34 2010 From: mercadal_diaz_ana at hotmail.com (ana mercadal diaz) Date: Thu, 12 Aug 2010 05:21:34 +0000 Subject: =?gb2312?B?yOe6zsjDxOPU9rzTtu7N4rXEytU=?= =?gb2312?B?yOujoXg=?= Message-ID: ?????? ????????,"?????????????????? ?????????????? ???????????? ???????????? ??????????? ??????????????? ?? ??????????????????????????????? 1. ???????????????2980???????????????? 2. ????????????? ?????????? ?????? 3. ????6?8?????????????DVD 4.??????????6800?????????????????DVD 5.??????? ??? ?????????????14????????????58000??????????????? ??????? ??????? ps??????10??????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From zn at wy.com Thu Aug 12 07:03:56 2010 From: zn at wy.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Thu, 12 Aug 2010 15:03:56 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsODAvOTC689K7z9/UsbmkudzA7Q==?= Message-ID: <201008120703.o7C73sXM003569@mx1.redhat.com> utrace-devel80/90????????? ?????2010?8?19-20? ?? ?????2010?8?21-22? ?? ?????2600?/????????????????? ?????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? --------------------------------------------------------------- ????: ?????????????????????? ???80/90??????????????????????????????????????,??80/90 ???????????????????????????????????80/90??????????? ??????????????????????????????????????????80/90???? ????????????????????????????????? ??????????????????????????80/90???????????????????? ???????80/90????????????????80/90????????????????????? 80/90?????????????????????????????????????????????? ??????80/90?????????????????????????80/90????? ----------------------------------------------------------------- ????? ? ??????????80/90?????????????????? ? ???????????????????????????? ? ???????????,??????,????????(?)??????? ?????????????????????????????? --------------------------------------------------------------------------------------- ??? ??????????? 80/90????????? 80/90?????,???????? ???????,??????? ??????1 ????????????????? ??????2 ??????????? ??? ??80/90??????(??)?? ??????, ?????? ??????, ?????? ??????, ?????? ??????, ??????? ??????, ??????? ??????, ?????? ??????, ?????? ??????, ?????? ??????1 ?????????? ??? ????80/90???????? ????,???? ????????? ????????? ????????80? 80/90?????? 80/90????? ??????3 ??????????? ??? 80/90????????????? ?????????? ?????????? ????????? ?????????? ??????4 ??????????????? ???????? 80/90?????? ??????5 80/90????????????? ??? ?????80/90????? ???????????? 80/90?????????? 80/90??????????? ??????6 ???? 80/90??????????? ??????2 ???????????? 80/90??????????? ??????3 ????? ??????7 ??????? ??? ??80/90????????? ??????? ??????? ??????? ??????? ??????2 ????????? ??????? ??????? ??????? ??????3 ??????????? ??? ??80/90????????? ????????? ??????4 ?????????????????? ????????? ??????8 ????????? ????????? ??????5? ???????? ????????? ??????6 ????????? ????????? ??????9 ???????? ????????? ????????? ??????7 ??????? ??? ?????????? ???????? ???????? ???????? ??????? ??????? ??????????? ??????10 ??????????? ????????? ???????? ??????8 ?????????? ??? ????????? ??????? ??????? ??????? ??????? ??????? ??????? --------------------------------------------------------------- ????: ???????????????MMC????.. ???????MMC??????????,????????????????????????????????? ??????????????????????JIT??????NPS???????????????????? ???????(??,??,??,??,??,??)???????????????????????????? ??????????????????????????????????????????????80/90?? ?????????????????????????????????????????????????? ?????????????ST??????? ?????????????????????????????????????????????ABB???? ???????????-??????????????????????????????????????? ?????????????????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????,???????????????????????????????? ???????????????????????????????? ------------------------------------------------------------------------------------------------------------- ?80/90?????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From fche at redhat.com Thu Aug 12 15:06:39 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 12 Aug 2010 11:06:39 -0400 Subject: gdbstub initial code, v3 In-Reply-To: <20100812011113.GA13212@redhat.com> (Oleg Nesterov's message of "Thu, 12 Aug 2010 03:11:13 +0200") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> Message-ID: oleg wrote: > [...] > - It doesn't support all-stop mode. > Please tell me if this is needed. I hope not, this needs > a lot of nasty complications :/ > [...] As opposed to non-stop mode? I'm pretty sure all-stop will be needed as that is the common & default gdb usage model. - FChE From hufhejifef11 at 21cn.net Thu Aug 12 17:51:35 2010 From: hufhejifef11 at 21cn.net (hufhejifef11 at 21cn.net) Date: Fri, 13 Aug 2010 01:51:35 +0800 (CST) Subject: =?UTF-8?B?5Yqo5L2c57KX5pq04oCc5oCn54ix4oCd56qS5oGv6ICM5Lqh?= =?UTF-8?B?LOS7rOWwseaDheeBteW6lOeIsea/gOW8seazleWcqOS7rA==?= Message-ID: <12522809.79331281635495257.JavaMail.root@pay4> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Aug 12 23:52:28 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Aug 2010 01:52:28 +0200 Subject: problems with v3 (Was: gdbstub initial code, v3) In-Reply-To: References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> Message-ID: <20100812235228.GA15051@redhat.com> On 08/11, Tom Tromey wrote: > > >>>>> "Oleg" == Oleg Nesterov writes: > > Oleg> So, the patch below fixes the problem, and gdb + /proc/ugdb seems > Oleg> to work. > > Oleg> Indeed, gdb sees that this fd is not pipe/tcp and uses the "hardwire" > Oleg> serial_ops, but hardwire_readchar() doesn't play well with select(). > > Oleg> Please teach gdb to use poll/select ? > > I looked at this a little bit. It seems to me that the "hardwire" stuff > is for talking to ttys, and we instead want gdb to be using the pipe code. I didn't verify this, but I don't think so. Please look at pipe_open(). Perhaps it makes sense to serial_add_interface("ugdb"), I dunno. OK. I was going to add some cleanups and send the new version today. But after some testing (without gdb) I hit the kernel crashes. This makes me think that probably something is wrong ;) As usual, I can't blame my code. I am still investigating, the crash is not easy to reproduce, but so far I _suspect_ the problems in utrace code. At least utrace_barrier()->signal_pending() is definitely not right. Will continue tomorrow. Oleg. From roland at redhat.com Fri Aug 13 01:02:08 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Aug 2010 18:02:08 -0700 (PDT) Subject: gdbstub initial code, v3 In-Reply-To: Oleg Nesterov's message of Thursday, 12 August 2010 04:37:50 +0200 <20100812023750.GA17011@redhat.com> References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> Message-ID: <20100813010208.E1739400E3@magilla.sf.frob.com> > Indeed, gdb sees that this fd is not pipe/tcp and uses the "hardwire" > serial_ops, but hardwire_readchar() doesn't play well with select(). > > Please teach gdb to use poll/select ? If it makes it easier, could use: bash$ nc -l -U /tmp/socket <> /proc/ugdb & (gdb) target remote |nc -U /tmp/socket for the moment. Silly of course, but just not to be blocked on cleaning up gdb's serial-device handling to be more nicely nonblocking. Thanks, Roland From tromey at redhat.com Fri Aug 13 01:44:59 2010 From: tromey at redhat.com (Tom Tromey) Date: Thu, 12 Aug 2010 19:44:59 -0600 Subject: problems with v3 In-Reply-To: <20100812235228.GA15051@redhat.com> (Oleg Nesterov's message of "Fri, 13 Aug 2010 01:52:28 +0200") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> Message-ID: >>>>> "Oleg" == Oleg Nesterov writes: Tom> I looked at this a little bit. It seems to me that the "hardwire" stuff Tom> is for talking to ttys, and we instead want gdb to be using the pipe code. Oleg> I didn't verify this, but I don't think so. Please look at pipe_open(). Yeah, I wasn't clear enough. I meant a hybrid with most code coming from ser-pipe.c. Oleg> Perhaps it makes sense to serial_add_interface("ugdb"), I dunno. I started a quick implementation of my idea, I'll finish it tomorrow. I think we should start an archer branch to hold whatever gdb hacks we need... I will do that tomorrow as well. Tom From roland at redhat.com Fri Aug 13 01:58:44 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Aug 2010 18:58:44 -0700 (PDT) Subject: problems with v3 In-Reply-To: Tom Tromey's message of Thursday, 12 August 2010 19:44:59 -0600 References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> Message-ID: <20100813015844.B7703400E3@magilla.sf.frob.com> I don't really know the gdb code, but I'm surprised it really has multiple different "serial" backends. I would have thought that after opening the fd, you would treat them all about the same. If tcsetattr et al work on it, then you set the baud rate and whatever, if they say ENOTTY then fine. It might make sense to default to a short read timeout for an actual serial port (or UDP port), which might be unplugged or the other end dead, or whatever; and to an infinite timeout for a non-tty, which should more presumably have its fd shut down and read EOF or EPIPE or whatever when the stub goes away, and otherwise perhaps the stub is just taking that long. But aside from that, I don't know why you wouldn't treat all kinds of remote protocol fd's the same wrt select/poll and blocking/nonblocking reads/writes, be they serial-port fds, "pipe" socketpair sockets, network sockets, or fds to a new magic file that pretends to be a tty or a socket or whatever (or even a disk file of canned response playback!). Thanks, Roland From tromey at redhat.com Fri Aug 13 04:37:18 2010 From: tromey at redhat.com (Tom Tromey) Date: Thu, 12 Aug 2010 22:37:18 -0600 Subject: problems with v3 In-Reply-To: <20100813015844.B7703400E3@magilla.sf.frob.com> (Roland McGrath's message of "Thu, 12 Aug 2010 18:58:44 -0700 (PDT)") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> Message-ID: Roland> I don't really know the gdb code, but I'm surprised it really Roland> has multiple different "serial" backends. I don't know this area well, but considering that ser-unix.c is just chock full of tty-related goo, I think it is probably important for something. My impression is that this API is not just used for target communication but also for manipulating gdb's own terminal. I looked closer and aside from open/close, ser-pipe is just falling back to some generic code. I've appended the patch I came up with. I have not tried it at all, but it should all be pretty obvious. Maybe I'd do it a little differently if this were going upstream. That doesn't seem necessary though. Tom diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index 266453c..672b2a8 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -32,6 +32,7 @@ #include "gdb_select.h" #include "gdb_string.h" #include "gdbcmd.h" +#include "gdb_stat.h" #ifdef HAVE_TERMIOS @@ -103,15 +104,56 @@ static int hardwire_setstopbits (struct serial *, int); void _initialize_ser_hardwire (void); +static struct serial_ops * +get_pipe_like_ops (void) +{ + static struct serial_ops *ops; + + if (ops == NULL) + { + ops = XMALLOC (struct serial_ops); + memset (ops, 0, sizeof (struct serial_ops)); + ops->name = NULL; + ops->open = NULL; + ops->close = hardwire_close; + ops->readchar = ser_base_readchar; + ops->write = ser_base_write; + ops->flush_output = ser_base_flush_output; + ops->flush_input = ser_base_flush_input; + ops->send_break = ser_base_send_break; + ops->go_raw = ser_base_raw; + ops->get_tty_state = ser_base_get_tty_state; + ops->set_tty_state = ser_base_set_tty_state; + ops->print_tty_state = ser_base_print_tty_state; + ops->noflush_set_tty_state = ser_base_noflush_set_tty_state; + ops->setbaudrate = ser_base_setbaudrate; + ops->setstopbits = ser_base_setstopbits; + ops->drain_output = ser_base_drain_output; + ops->async = ser_base_async; + ops->read_prim = ser_unix_read_prim; + ops->write_prim = ser_unix_write_prim; + } + + return ops; +} + /* Open up a real live device for serial I/O */ static int hardwire_open (struct serial *scb, const char *name) { + struct stat buf; + scb->fd = open (name, O_RDWR); if (scb->fd < 0) return -1; + if (fstat (scb->fd, &buf) == 0 && S_ISFIFO (buf.st_mode)) + { + /* Super hack! */ + scb->ops = get_pipe_like_ops (); + } + return 0; } From roland at redhat.com Fri Aug 13 08:29:49 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 13 Aug 2010 01:29:49 -0700 (PDT) Subject: problems with v3 In-Reply-To: Tom Tromey's message of Thursday, 12 August 2010 22:37:18 -0600 References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> Message-ID: <20100813082949.93D1E400E3@magilla.sf.frob.com> > I don't know this area well, but considering that ser-unix.c is just > chock full of tty-related goo, I think it is probably important for > something. My impression is that this API is not just used for target > communication but also for manipulating gdb's own terminal. Ah, I see. > I've appended the patch I came up with. I have not tried it at all, but > it should all be pretty obvious. Yeah, that seems like it should be reasonable, i.e. more or less like what I'd figured it would do if it didn't have all these different backends. However, I think the test you probably want is !S_ISCHR. I believe that /proc/ugdb as is stats as S_ISREG, not S_ISFIFO. Actually, better yet, just make it !isatty (fd). Another pseudodevice that also behaves more like a socket than like a tty might be S_ISCHR, but only a tty isatty. Thanks, Roland From sales006 at 28581848.cn Fri Aug 13 12:16:14 2010 From: sales006 at 28581848.cn (kiko-america logistics) Date: Fri, 13 Aug 2010 20:16:14 +0800 Subject: shipping agent in shenzhen china! Message-ID: <201008131338.o7DDceeP028175@mx2.redhat.com> Dear Friend, This is Kiko , from Shipping Agent in China. I get your email from your website. I send email to you because i want to work with you. I think you have Fob cargo pls choose me we will reduce your cost. We America Shipping China, can provide competitive O/F from China to South &North America/Africa/Europe and so on. We also can Air freight. We also have competitive rate on other place container. So if you have cargo move , you must let me know , i will offer you a surprise rate . Enclosed our rate pls kindly find. Fob shenzhen--los angeles Ocean Freight:USD1950/2450/2650 T/T:15days Fob shenzhen--New york/Miami/Savannah/Norfolk Ocean Freight:USD3350/4150/4400 T/T::24days/26days/28days Fob shenzhen--Ashdod/Beitut/Lattakia Ocean Freight:USD2050/3950/4050 T/T::23days/25days/25days Fob shenzhen--Abidjan/Tema/Apapa/Cotonou Ocean Freight:USD1950/3750/3850 Above rate valid till to Aug 15,2010 If this E-mail disturbs you and causes inconvenience, please inform us, and it will be stopped! Kind regards Oversea Dept : Kiko *************************************************************** America International Logistics(ShenZhen) Co.,Ltd Tel: 86-0755-82020113 Fax:86-0755-82020123 Moblie:13554866206 Skype:americalogistics888 QQ:385369704 E-mail:kiko at americalogi.com.cn Msn:kiko198263 at hotmail.com Http://www.americalogi.com.cn ADD;1708 BLOCK B, Business Building, South International Plaza, Fu Tian DISTRICT,Shen Zhen City, Guang Dong ,China -------------- next part -------------- An HTML attachment was scrubbed... URL: From dan at codesourcery.com Fri Aug 13 14:08:39 2010 From: dan at codesourcery.com (Daniel Jacobowitz) Date: Fri, 13 Aug 2010 10:08:39 -0400 Subject: problems with v3 In-Reply-To: References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> Message-ID: <20100813140836.GA23004@caradoc.them.org> On Thu, Aug 12, 2010 at 10:37:18PM -0600, Tom Tromey wrote: > Roland> I don't really know the gdb code, but I'm surprised it really > Roland> has multiple different "serial" backends. > > I don't know this area well, but considering that ser-unix.c is just > chock full of tty-related goo, I think it is probably important for > something. My impression is that this API is not just used for target > communication but also for manipulating gdb's own terminal. Correct. Also, the abstraction layer is important on non-Unix systems; "everything is a file descriptor" works poorly on Windows :-) -- Daniel Jacobowitz CodeSourcery From whung at bellsouth.net Fri Aug 13 16:02:07 2010 From: whung at bellsouth.net (zukn) Date: Sat, 14 Aug 2010 00:02:07 +0800 Subject: =?gb2312?B?z/pfyttgvqtf06IyzOzSu9K5t+hgv/HRtWDBtyc9Ww==?= Message-ID: <20100814000219034565@bellsouth.net> ? ? ? ? ? ? ? ? ?! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ? ? ? ?2???? ?? ?.doc Type: application/msword Size: 35840 bytes Desc: not available URL: From tromey at redhat.com Fri Aug 13 16:31:44 2010 From: tromey at redhat.com (Tom Tromey) Date: Fri, 13 Aug 2010 10:31:44 -0600 Subject: problems with v3 In-Reply-To: <20100813082949.93D1E400E3@magilla.sf.frob.com> (Roland McGrath's message of "Fri, 13 Aug 2010 01:29:49 -0700 (PDT)") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> <20100813082949.93D1E400E3@magilla.sf.frob.com> Message-ID: Roland> However, I think the test you probably want is !S_ISCHR. Thanks. I wasn't sure. Roland> Actually, better yet, just make it !isatty (fd). Ok. I made a new branch, 'archer-ugdb'. This patch is there. (Actually 2 patches due to me not reading carefully enough the first time -- but whatever.) Oleg, use this branch and give the feature a try. We can push whatever fixes or hacks you need to this branch. I can also merge from gdb's master as needed. Tom From oleg at redhat.com Fri Aug 13 20:53:19 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Aug 2010 22:53:19 +0200 Subject: problems with v3 (Was: gdbstub initial code, v3) In-Reply-To: <20100812235228.GA15051@redhat.com> References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> Message-ID: <20100813205319.GA18689@redhat.com> On 08/13, Oleg Nesterov wrote: > > As usual, I can't blame my code. I am still investigating, the crash > is not easy to reproduce, but so far I _suspect_ the problems in utrace > code. At least utrace_barrier()->signal_pending() is definitely not > right. I seem to understand the problem(s). I am a bit surprized. Basically I have the questions about almost every utrace_ function. I'll try to recheck and summarize my concerns tomorrow with a fresh head, I hope I missed something. And I think at least we should cleanup utrace_set_events(), I'll try to send the patch a bit later. Oleg. From oleg at redhat.com Fri Aug 13 21:12:24 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Aug 2010 23:12:24 +0200 Subject: problems with v3 In-Reply-To: References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> <20100813082949.93D1E400E3@magilla.sf.frob.com> Message-ID: <20100813211224.GB18689@redhat.com> On 08/13, Tom Tromey wrote: > > Roland> However, I think the test you probably want is !S_ISCHR. > > Thanks. I wasn't sure. > > Roland> Actually, better yet, just make it !isatty (fd). > > Ok. Good. IIUC, this also allows to remove the ugly "return 0 to pretend TCGETS/TCSETS/TCFLSH works" from ->ioctl(). > I made a new branch, 'archer-ugdb'. I assume, you mean git://sourceware.org/git/gdb.git ? > This patch is there. (Actually 2 patches due to me not reading > carefully enough the first time -- but whatever.) > > Oleg, use this branch and give the feature a try. Yes, once I resolve the current problems I'll test it. Thanks! Oleg. From tromey at redhat.com Fri Aug 13 21:18:17 2010 From: tromey at redhat.com (Tom Tromey) Date: Fri, 13 Aug 2010 15:18:17 -0600 Subject: problems with v3 In-Reply-To: <20100813211224.GB18689@redhat.com> (Oleg Nesterov's message of "Fri, 13 Aug 2010 23:12:24 +0200") References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813015844.B7703400E3@magilla.sf.frob.com> <20100813082949.93D1E400E3@magilla.sf.frob.com> <20100813211224.GB18689@redhat.com> Message-ID: Tom> I made a new branch, 'archer-ugdb'. Oleg> I assume, you mean git://sourceware.org/git/gdb.git ? git://sourceware.org/git/archer.git I can give you write access to this repository if you want. Just let me know. Tom From roland at redhat.com Fri Aug 13 21:31:09 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 13 Aug 2010 14:31:09 -0700 (PDT) Subject: problems with v3 (Was: gdbstub initial code, v3) In-Reply-To: Oleg Nesterov's message of Friday, 13 August 2010 22:53:19 +0200 <20100813205319.GA18689@redhat.com> References: <20100811235810.GA9783@redhat.com> <20100812011113.GA13212@redhat.com> <20100812023750.GA17011@redhat.com> <20100812235228.GA15051@redhat.com> <20100813205319.GA18689@redhat.com> Message-ID: <20100813213109.34788400E3@magilla.sf.frob.com> > I seem to understand the problem(s). I am a bit surprized. Basically > I have the questions about almost every utrace_ function. I'll try > to recheck and summarize my concerns tomorrow with a fresh head, I > hope I missed something. Ok. That stuff about pure kernel implementation issues doesn't need to go to the archer list and Tom, only to utrace-devel. Thanks, Roland From lopezmotoso at hotmail.com Sat Aug 14 01:40:13 2010 From: lopezmotoso at hotmail.com (Marcelo Lopez Motoso) Date: Sat, 14 Aug 2010 01:40:13 +0000 Subject: =?gb2312?B?ztLSqrzeuPjE4y4uLi44?= =?gb2312?Q?5q?= Message-ID: ?????? ??????????????N?????????K????-?????????? ???????,?????K??????N????????????????W????? ?????????K????????? ???????????????? 1.??????X-????B?? ????? 2.???24??C?10???? ????K? 3.??????R-???? ????? ?????????????8???????????I?????????????? ??????? ps?????????B???????????I??????? ??????????R????????-??17???Z??? ???????????????P??????B -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sat Aug 14 02:31:24 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 14 Aug 2010 04:31:24 +0200 Subject: [PATCH 1/4] utrace_set_events: make the death/reap checks readable Message-ID: <20100814023124.GA9229@redhat.com> No changes in the compiled code. Just make the code parsable by humans. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) --- kstub/kernel/utrace.c~1_use_cleanup_exit_state_checks 2010-08-14 04:28:58.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-14 04:30:28.000000000 +0200 @@ -539,13 +539,15 @@ int utrace_set_events(struct task_struct old_utrace_flags = target->utrace_flags; old_flags = engine->flags & ~ENGINE_STOP; - if (target->exit_state && - (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || - (utrace->death && - ((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) || - (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) { - spin_unlock(&utrace->lock); - return -EALREADY; + if (target->exit_state) { + unsigned long cleared = (old_flags & ~events); + + if (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || + (utrace->death && (cleared & _UTRACE_DEATH_EVENTS)) || + (utrace->reap && (cleared & UTRACE_EVENT(REAP)))) { + spin_unlock(&utrace->lock); + return -EALREADY; + } } /* From oleg at redhat.com Sat Aug 14 02:31:28 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 14 Aug 2010 04:31:28 +0200 Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case Message-ID: <20100814023128.GA9236@redhat.com> I am not sure this fix is really needed, up to you. But please note that this code if ((utrace->death && (cleared & _UTRACE_DEATH_EVENTS)) || (utrace->reap && (cleared & UTRACE_EVENT(REAP)))) { spin_unlock(&utrace->lock); return -EALREADY; } is not exactly right, it has 2 minor problems: - It is possible that both ->death and ->reap are true. In this case it is OK to clear UTRACE_EVENT(REAP), but set_events fails. - OTOH, if ->reap is true, set_events disallows "clear" but allows "set", the latter case should be forbidden too. If utrace_set_events(UTRACE_EVENT(REAP)) succeeds, the caller has all rights to expect ->report_reap() will be caller later. If you take this patch, then please consider the next one. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) --- kstub/kernel/utrace.c~3_minor_death_reap_fix 2010-08-14 04:30:28.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-14 04:30:29.000000000 +0200 @@ -541,12 +541,16 @@ int utrace_set_events(struct task_struct /* If ->death or ->reap is true we must see exit_state != 0. */ if (target->exit_state) { - unsigned long cleared = (old_flags & ~events); - - if ((utrace->death && (cleared & _UTRACE_DEATH_EVENTS)) || - (utrace->reap && (cleared & UTRACE_EVENT(REAP)))) { - spin_unlock(&utrace->lock); - return -EALREADY; + if (utrace->death) { + if ((old_flags & ~events) & _UTRACE_DEATH_EVENTS) { + spin_unlock(&utrace->lock); + return -EALREADY; + } + } else if (utrace->reap) { + if ((old_flags ^ events) & UTRACE_EVENT(REAP)) { + spin_unlock(&utrace->lock); + return -EALREADY; + } } } From oleg at redhat.com Sat Aug 14 02:31:30 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 14 Aug 2010 04:31:30 +0200 Subject: [PATCH 4/4] utrace_set_events: use goto to return -EALREADY Message-ID: <20100814023130.GA9243@redhat.com> utrace_set_events() is not trivial, and imho it has too much "unlock + return" cases. Change the code to use goto, this also lessens the source and compiled code a bit. --- kernel/utrace.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) --- kstub/kernel/utrace.c~4_cleanup_ealready 2010-08-14 04:30:29.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-14 04:30:29.000000000 +0200 @@ -524,7 +524,7 @@ int utrace_set_events(struct task_struct { struct utrace *utrace; unsigned long old_flags, old_utrace_flags; - int ret; + int ret = -EALREADY; /* * We just ignore the internal bit, so callers can use @@ -542,15 +542,11 @@ int utrace_set_events(struct task_struct /* If ->death or ->reap is true we must see exit_state != 0. */ if (target->exit_state) { if (utrace->death) { - if ((old_flags & ~events) & _UTRACE_DEATH_EVENTS) { - spin_unlock(&utrace->lock); - return -EALREADY; - } + if ((old_flags & ~events) & _UTRACE_DEATH_EVENTS) + goto unlock; } else if (utrace->reap) { - if ((old_flags ^ events) & UTRACE_EVENT(REAP)) { - spin_unlock(&utrace->lock); - return -EALREADY; - } + if ((old_flags ^ events) & UTRACE_EVENT(REAP)) + goto unlock; } } @@ -568,8 +564,7 @@ int utrace_set_events(struct task_struct read_lock(&tasklist_lock); if (unlikely(target->exit_state)) { read_unlock(&tasklist_lock); - spin_unlock(&utrace->lock); - return -EALREADY; + goto unlock; } target->utrace_flags |= events; read_unlock(&tasklist_lock); @@ -597,7 +592,7 @@ int utrace_set_events(struct task_struct if (utrace->reporting == engine) ret = -EINPROGRESS; } - +unlock: spin_unlock(&utrace->lock); return ret; From undraw at varela.cl Sat Aug 14 10:24:05 2010 From: undraw at varela.cl (Lonero Aadland) Date: Sat, 14 Aug 2010 12:24:05 +0200 Subject: Your wife photos attached Message-ID: <4C666CF2.5020707@varela.cl> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: reflationary.zip Type: application/octet-stream Size: 11077 bytes Desc: not available URL: From fgfu at gdt.com Sat Aug 14 22:29:15 2010 From: fgfu at gdt.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sun, 15 Aug 2010 06:29:15 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0MKy+sa30dC3osH3s8zTxbuv0+u53MDt?= Message-ID: <201008142229.o7EMTDck015296@mx1.redhat.com> utrace-devel???????????????? ?????2010?8?21-22? ?? ?????2010?9?25-26? ?? ???????????????????????????????????????? ???????????????? ?====??2600?/2?/?(???????????????????????) ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ====================================================================================== ???? ?. ????????????????? ?. ??????????????????? ?. ?????????????????????? ?. ?????????????????? ?. ??????????????????? ?. ??????????????????? ?. ???????????????????? ?. ???????????????? ?. ????????????????????????????????????????????? ?. ????????????????????????????????????????? ?. ???????????????????????????????????? ?. ???????????????????????? ?. ???????????????????????????????? ?. ??????????????????????????????????????? ??Action Plan??????????????????????????????? ====================================================================================== ???? ????????????????? 1???????????????????????????IT???? 2???????????? 3???????????????? ?????????? 1???????????????? 2???????? 3???????????????????????????????? 4???????????????? 5?????????????????? 6??????????????? 7???????? ???????????? 1?????????????? 2?????????????????????? 3????????????????? 4?????????????????? a)??????????????????????????????? b)????????????????????? c)????????????????? d)????????????????? e)??????????????????????? 5????????????????????????????????????????? ??????????????????????? 6????????????????????? 7???????IT????????????????? 8???????? ???????????? 1?????????????? 2????????????????? 3???????????? a??????????? b?????????????? c?????????????? d????????????? e?????????????????????? 4???????????????????? a) ?????? b) ?????? c)??????????? d)??????????????? 5??????????????????????? * ????????????????? 6???????? ????????????????????????????????? 1??????????????????????????????????????????? ??????????????????????????????????????????? ??????????? 2????????????? 3?????????????????????????? 4??????????????????????????????????? 5????????????????? 6?????????????? 7???????????? 8???????????? 9????????? 10?????????? 11?????????PMO? 12?????????????? 13???????IT????????????? 14????????????????? 15??????????Check List????????? 16???????IT??????????? ????????????? 1???????? a)?????? b)?????? 2???????? a)????????????????????? b)????????? c)??????????? d)????????? e)????????? f)??????????????? g)?????????????? h)WBS????????? i)WBS??????? j)PBS?WBS?OBS?RBS??????? k)????????? l)??????????? m)PERT???? n)?????????? *????? *????? o)??????? ????????????? 1??????????????????? 2????????????? 3????? a)?????? b)??????? c)??????? 4?????????????? a) ?????? b) ?????? 5?????????????? a) ?????? b) ??????? 6???????????????? a) ?????? b) ?????? 7?????????????? 8???????????????? 9????????????????? 10?????????????? 11???????????????? 12?????????????? a) ???????? b) ???? c) ???????? 13???????? ?????????? 1?????????? 2?????????BSC?KPI?????????????? 3????????PBC?PIP 4????????? a. ?????????????? b. ??????? c. ??????? ??????????????????? 1???????????????????????????????????????? 2???????IT????????????????? 3???????????? 4???????????? 5??????????? 6?????????????? 7?????????????? ====================================================================================== ?????????? ???????????????????????? ??????????? ==>??????????? ???? & ????? ==>???????????????????????? ?????? ???????????????????????????????????????????? ???????? ???????????????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????? ???????????????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????????????? ????????????? ==>?????????? ==>????????????? ==>????????????? ==>???????????????????? ??????????????? ????????????????????????????? ???????????????????(??)??????? ??????????????????????????????,????????92%??,?? ?????????????????????,????????????????? =============================================================================== ???????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From equivalenced at imageserve.com Mon Aug 16 06:10:28 2010 From: equivalenced at imageserve.com (Fortin Canup) Date: Mon, 16 Aug 2010 08:10:28 +0200 Subject: Your wife photos attached Message-ID: <4C68D60A.6090506@imageserve.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: bulnbuln.zip Type: application/octet-stream Size: 10655 bytes Desc: not available URL: From oleg at redhat.com Mon Aug 16 09:39:24 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 11:39:24 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes Message-ID: <20100816093924.GA24425@redhat.com> On top of utrace_set_events() 1-4 fixes I sent. utrace_barrier() needs more fixes, I'll send them separately. Untested, but still I am asking for your review. Of course I am going to test these changes later, but I'm afraid the thorough review is much more important, it is not clear to me how it is possible to really test the changes like this. Oleg. From oleg at redhat.com Mon Aug 16 09:39:26 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 11:39:26 +0200 Subject: [PATCH 1/3] get_utrace_lock() must not succeed if utrace->reap == T Message-ID: <20100816093926.GA24429@redhat.com> get_utrace_lock() must threat utrace->reap == T as engine->ops == NULL. The logic in get_utrace_lock() is correct. If we see engine->ops != NULL under rcu_read_lock(), the target has not passed release_task() yet, so it is safe to dereference target/utrace and take utrace->lock. However. If utrace->reap is true it is not safe to use target/utrace after return from get_utrace_lock(), it drops rcu_read_lock() and returns with utrace->lock held, but spin_lock() doesn't imply RCU lock. IOW. Suppose that get_utrace_lock() is called after utrace_maybe_reap() unlocks utrace->lock() and before it starts the last REAP reporting loop. It is very possible engine has the valid ->ops != utrace_detached_ops, in this case get_utrace_lock() succeeds. But, nothing protects from release_task()->call_rcu(delayed_put_task_struct) after that, this means that the caller of get_utrace_lock() can't access target/utrace after rcu_read_unlock(). Let's see how this change affect the callers: - utrace_barrier() - please ignore. It needs fixes with or without this change. - utrace_control() is not affected except this change makes the utrace->reap check in utrace_control_dead() unnecessary. - utrace_set_events() is obviously affected, but imho this is good. Really, we can do nothing with target/engine if ->reap is true. What is the point to allow to change engine->flags when we know that the target is under destruction? Again, this makes utrace->reap check unnecessary, we can remove it. I already sent the preparation changes which separated ->death/reap checks, I am waiting for your reply. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- kstub/kernel/utrace.c~5_get_lock_must_check_reap 2010-08-14 04:30:29.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-16 11:17:05.000000000 +0200 @@ -421,7 +421,7 @@ static struct utrace *get_utrace_lock(st utrace = task_utrace_struct(target); spin_lock(&utrace->lock); - if (unlikely(!engine->ops) || + if (unlikely(utrace->reap) || unlikely(!engine->ops) || unlikely(engine->ops == &utrace_detached_ops)) { /* * By the time we got the utrace lock, From oleg at redhat.com Mon Aug 16 09:39:29 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 11:39:29 +0200 Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction Message-ID: <20100816093929.GA24436@redhat.com> Suppose that we want to detach the engine and free engine->data. To avoid the races with our calbacks which can use ->data we should do either err = utrace_set_events(0); if (err == ...) utrace_barrier(); utrace_control(DETACH); or err = utrace_control(DETACH); if (err = ...) utrace_barrier(); Neither variant works if we should care about report_quiesce() or report_death(). Let's discuss the 2nd case, the 1st one have the similar problems. The problem is, utrace_control(DETACH) does nothing and returns -EALREADY if utrace->death is set, this is not right. We can and should detach in this case, we only should skip utrace_reset() to avoid the race with utrace_report_death()->REPORT_CALLBACKS(). This was the main problem I hit during the testing. Consider the exiting tracee with the valid engine->ops, suppose that utrace_control(DETACH) is called right after utrace_report_death() unlocks utrace->lock and before it does REPORT_CALLBACKS(). utrace_control() fails, but utrace_barrier() does not help after that. It takes get_utrace_lock() successfully and returns 0. The caller frees engine->data, but utrace_report_death() calls ->report_death() after that. Kill utrace_control_dead(). Change utrace_control() to always allow UTRACE_DETACH if engine has the valid ->ops. This means that mark_engine_detached() can race with REPORT_CALLBACKS() but there is nothing new. utrace_do_stop() is unnecessary and pointless in this case, but it doesn't hurt. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 49 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 39 deletions(-) --- kstub/kernel/utrace.c~6_fix_control_dead 2010-08-16 11:17:05.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-16 11:17:51.000000000 +0200 @@ -928,37 +928,6 @@ void utrace_maybe_reap(struct task_struc } } -/* - * You can't do anything to a dead task but detach it. - * If release_task() has been called, you can't do that. - * - * On the exit path, DEATH and QUIESCE event bits are set only - * before utrace_report_death() has taken the lock. At that point, - * the death report will come soon, so disallow detach until it's - * done. This prevents us from racing with it detaching itself. - * - * Called only when @target->exit_state is nonzero. - */ -static inline int utrace_control_dead(struct task_struct *target, - struct utrace *utrace, - enum utrace_resume_action action) -{ - lockdep_assert_held(&utrace->lock); - - if (action != UTRACE_DETACH || unlikely(utrace->reap)) - return -ESRCH; - - if (unlikely(utrace->death)) - /* - * We have already started the death report. We can't - * prevent the report_death and report_reap callbacks, - * so tell the caller they will happen. - */ - return -EALREADY; - - return 0; -} - /** * utrace_control - control a thread being traced by a tracing engine * @target: thread to affect @@ -1115,18 +1084,20 @@ int utrace_control(struct task_struct *t ret = 0; /* - * ->exit_state can change under us, this doesn't matter. - * We do not care about ->exit_state in fact, but we do - * care about ->reap and ->death. If either flag is set, - * we must also see ->exit_state != 0. + * ->exit_state can change under us, this doesn't matter. But, + * if utrace->death is set we must also see ->exit_state != 0, + * this is what we care about. */ if (unlikely(target->exit_state)) { - ret = utrace_control_dead(target, utrace, action); - if (ret) { + /* You can't do anything to a dead task but detach it */ + if (action != UTRACE_DETACH) { spin_unlock(&utrace->lock); - return ret; + return -ESRCH; } - reset = true; + + /* If it is not set, we can safely do utrace_reset() */ + if (likely(!utrace->death)) + reset = true; } switch (action) { From oleg at redhat.com Mon Aug 16 09:39:31 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 11:39:31 +0200 Subject: [PATCH 3/3] utrace_set_events: kill now unnecessary exit_state/reap checks Message-ID: <20100816093931.GA24439@redhat.com> Now that get_utrace_lock() can never succeed if utrace->reap is true, we can kill this check in utrace_set_events(). This also means we can kill the target->exit_state check, it buys nothing now. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) --- kstub/kernel/utrace.c~7_set_events_kill_reap 2010-08-16 11:17:51.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-16 11:28:00.000000000 +0200 @@ -539,15 +539,10 @@ int utrace_set_events(struct task_struct old_utrace_flags = target->utrace_flags; old_flags = engine->flags & ~ENGINE_STOP; - /* If ->death or ->reap is true we must see exit_state != 0. */ - if (target->exit_state) { - if (utrace->death) { - if ((old_flags & ~events) & _UTRACE_DEATH_EVENTS) - goto unlock; - } else if (utrace->reap) { - if ((old_flags ^ events) & UTRACE_EVENT(REAP)) - goto unlock; - } + if ((old_flags & ~events) & _UTRACE_DEATH_EVENTS) { + /* Too late if utrace_report_death() is in progress */ + if (utrace->death) + goto unlock; } /* From oleg at redhat.com Mon Aug 16 14:51:49 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 16:51:49 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100816093924.GA24425@redhat.com> References: <20100816093924.GA24425@redhat.com> Message-ID: <20100816145149.GA7801@redhat.com> On 08/16, Oleg Nesterov wrote: > > On top of utrace_set_events() 1-4 fixes I sent. > > utrace_barrier() needs more fixes, I'll send them separately. Later. > Untested, but still I am asking for your review. Of course I am > going to test these changes later, but I'm afraid the thorough > review is much more important, it is not clear to me how it is > possible to really test the changes like this. Well, I tried to test these changes, seems to work. But... From 2/3 changelog: This means that mark_engine_detached() can race with REPORT_CALLBACKS() but there is nothing new. Yes, there is nothing new. But, Roland, this is WRONG! With or without these fixes utrace_control()->mark_engine_detached() was always wrong if it races with REPORT/REPORT_CALLBACKS. Not sure what we were thinking about :/ Look. Suppose that utrace_control(DETACH) is called right after start_callback() returns ops != NULL. After that finish_callback(..., ops->callback(...)) can hit ->callback == NULL! The obvious and simplest solution: utrace_detached_ops{} should have the dummy handler for every callback. But I'd like to think a bit more. Oleg. From oleg at redhat.com Mon Aug 16 15:09:39 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 17:09:39 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100816145149.GA7801@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> Message-ID: <20100816150939.GA8842@redhat.com> On 08/16, Oleg Nesterov wrote: > > Well, I tried to test these changes, seems to work. > > But... From 2/3 changelog: > > This means that > mark_engine_detached() can race with REPORT_CALLBACKS() but there > is nothing new. > > Yes, there is nothing new. But, Roland, this is WRONG! > > With or without these fixes utrace_control()->mark_engine_detached() > was always wrong if it races with REPORT/REPORT_CALLBACKS. Not sure > what we were thinking about :/ > > Look. Suppose that utrace_control(DETACH) is called right after > start_callback() returns ops != NULL. After that > finish_callback(..., ops->callback(...)) can hit ->callback == NULL! Cough. I guess I spent too much time with utrace and testing today ;) Let me try again. mark_engine_detached() does engine->ops = &utrace_detached_ops; smp_wmb(); engine->flags = UTRACE_EVENT(QUIESCE); Whatever we do, start_callback() can see the old engine->flags but the new ->ops = &utrace_detached_ops. Just suppose that the caller of UTRACE_DETACH is interrupted right after setting engine->ops. > The obvious and simplest solution: utrace_detached_ops{} should > have the dummy handler for every callback. But I'd like to think > a bit more. Yes. Perhaps (unlikely) we can reverse the order, but I can no longer think properly today. Or do you think I miss something and this is false alarm? Oleg. From oleg at redhat.com Mon Aug 16 15:19:46 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Aug 2010 17:19:46 +0200 Subject: [PATCH 2/4] utrace_set_events: consolidate "setting _UTRACE_DEATH_EVENTS" checks In-Reply-To: <20100814023126.GA9233@redhat.com> References: <20100814023126.GA9233@redhat.com> Message-ID: <20100816151946.GA9352@redhat.com> Hmm. For unknown reason I do not see this 2/4 patch on utrace-devel, strange. So I am attaching it in case my email was really lost and you didn't get it. Oleg. -------------- next part -------------- [PATCH 2/4] utrace_set_events: consolidate "setting _UTRACE_DEATH_EVENTS" checks utrace_set_events() checks the "setting _UTRACE_DEATH_EVENTS" case twice, and it is not immediately obvious why the first check is needed, and why it is not racy (we are checking exit_state without tasklist). The code is correct, but looks confusing. The first check covers the case when target->utrace_flags already has _UTRACE_DEATH_EVENTS and thus tracehook_report_death() can't bypass utrace_report_death(), but we should ensure that REPORT_CALLBACKS() was not called yet. We can check ->exit_state lockless because it must be visible when utrace_report_death() unlocks utrace->lock. The second check ensures we can't race with tracehook_report_death() which checks task_utrace_flags(), so if we add _UTRACE_DEATH_EVENTS to ->utrace_flags we have to take tasklist. In short: this double check allows to avoid tasklist when utrace_flags already has these bits while engine->flags doesn't. But multitracing is unlikely case, in the likely case if we add _UTRACE_DEATH_EVENTS to engine->flags we set these bits in utrace_flags too. I think it makes sense to consolidate these checks to make the code a bit more understandable. Also, add the small comment to explain the lockless exit_state check. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- kstub/kernel/utrace.c~2_consolidate_death_events_checks 2010-08-14 04:30:28.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-14 04:30:28.000000000 +0200 @@ -539,11 +539,11 @@ int utrace_set_events(struct task_struct old_utrace_flags = target->utrace_flags; old_flags = engine->flags & ~ENGINE_STOP; + /* If ->death or ->reap is true we must see exit_state != 0. */ if (target->exit_state) { unsigned long cleared = (old_flags & ~events); - if (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || - (utrace->death && (cleared & _UTRACE_DEATH_EVENTS)) || + if ((utrace->death && (cleared & _UTRACE_DEATH_EVENTS)) || (utrace->reap && (cleared & UTRACE_EVENT(REAP)))) { spin_unlock(&utrace->lock); return -EALREADY; @@ -560,7 +560,7 @@ int utrace_set_events(struct task_struct * knows positively that utrace_report_death() will be called or * that it won't. */ - if ((events & ~old_utrace_flags) & _UTRACE_DEATH_EVENTS) { + if ((events & ~old_flags) & _UTRACE_DEATH_EVENTS) { read_lock(&tasklist_lock); if (unlikely(target->exit_state)) { read_unlock(&tasklist_lock); From roland at redhat.com Mon Aug 16 23:46:38 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 16:46:38 -0700 (PDT) Subject: [PATCH 2/4] utrace_set_events: consolidate "setting _UTRACE_DEATH_EVENTS" checks In-Reply-To: Oleg Nesterov's message of Monday, 16 August 2010 17:19:46 +0200 <20100816151946.GA9352@redhat.com> References: <20100814023126.GA9233@redhat.com> <20100816151946.GA9352@redhat.com> Message-ID: <20100816234638.C63524007E@magilla.sf.frob.com> > Hmm. For unknown reason I do not see this 2/4 patch on utrace-devel, > strange. > > So I am attaching it in case my email was really lost and you didn't > get it. Indeed, it did not come through to me or the list. Thanks, Roland From roland at redhat.com Tue Aug 17 00:00:54 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 17:00:54 -0700 (PDT) Subject: [PATCH 2/4] utrace_set_events: consolidate "setting _UTRACE_DEATH_EVENTS" checks In-Reply-To: Oleg Nesterov's message of Monday, 16 August 2010 17:19:46 +0200 <20100816151946.GA9352@redhat.com> References: <20100814023126.GA9233@redhat.com> <20100816151946.GA9352@redhat.com> Message-ID: <20100817000054.6C9424007E@magilla.sf.frob.com> > utrace_set_events() checks the "setting _UTRACE_DEATH_EVENTS" case twice, > and it is not immediately obvious why the first check is needed, and why > it is not racy (we are checking exit_state without tasklist). The code is > correct, but looks confusing. More comments are always good. > In short: this double check allows to avoid tasklist when utrace_flags > already has these bits while engine->flags doesn't. > > But multitracing is unlikely case, in the likely case if we add > _UTRACE_DEATH_EVENTS to engine->flags we set these bits in utrace_flags > too. I think it makes sense to consolidate these checks to make the > code a bit more understandable. I don't really agree about "unlikely case". In many uses, the systemtap task-finder will have a utrace engine on every task in the system, for example. Moreover, this is an importantly distinct particular kind of micro-optimization to be doing here: avoiding a system-wide lock. Any place that we take tasklist_lock at all, we are introducing a system-wide slowdown or limitation on scaling, just because of our tracing of one task. So optimizing the minimize that is qualitatively different and really much more important than avoiding taking the utrace lock, for example. But with that note in your mind, I am happy to take this patch now as a simplification and let reoptimization come back later. Thanks, Roland From roland at redhat.com Tue Aug 17 00:13:08 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 17:13:08 -0700 (PDT) Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case In-Reply-To: Oleg Nesterov's message of Saturday, 14 August 2010 04:31:28 +0200 <20100814023128.GA9236@redhat.com> References: <20100814023128.GA9236@redhat.com> Message-ID: <20100817001308.D335D4007E@magilla.sf.frob.com> > - It is possible that both ->death and ->reap are true. In this > case it is OK to clear UTRACE_EVENT(REAP), but set_events fails. No, it's not OK to clear it. Once ->reap is set, then the engine's ops->report_reap might or might not have been called already. If utrace_set_events() returns 0, then it's claiming a guarantee that the clearing of the bit took effect and no callback can be made. The only way it could be reliable in practice is if the caller is inside the report_death callback or synchronizing with it. In that situation, the engine should just return UTRACE_DETACH from its report_death callback. > - OTOH, if ->reap is true, set_events disallows "clear" but allows > "set", the latter case should be forbidden too. > > If utrace_set_events(UTRACE_EVENT(REAP)) succeeds, the caller > has all rights to expect ->report_reap() will be caller later. Correct. > If you take this patch, then please consider the next one. Ok. Thanks, Roland From roland at redhat.com Tue Aug 17 00:30:42 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 17:30:42 -0700 (PDT) Subject: [PATCH 1/3] get_utrace_lock() must not succeed if utrace->reap == T In-Reply-To: Oleg Nesterov's message of Monday, 16 August 2010 11:39:26 +0200 <20100816093926.GA24429@redhat.com> References: <20100816093926.GA24429@redhat.com> Message-ID: <20100817003042.EBDC44007E@magilla.sf.frob.com> > get_utrace_lock() must threat utrace->reap == T as engine->ops == NULL. Yes, I think you're right. This requires some changes to the kerneldoc and utrace.tmpl, because it now says that you get EALREADY if report_reap is already running. Now it will be consistent with utrace_control, where you get ESRCH either if report_reap might already be running or if it's entirely detached and/or reaped. Thanks, Roland From roland at redhat.com Tue Aug 17 00:44:43 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 17:44:43 -0700 (PDT) Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction In-Reply-To: Oleg Nesterov's message of Monday, 16 August 2010 11:39:29 +0200 <20100816093929.GA24436@redhat.com> References: <20100816093929.GA24436@redhat.com> Message-ID: <20100817004443.D95244007E@magilla.sf.frob.com> > The problem is, utrace_control(DETACH) does nothing and returns > -EALREADY if utrace->death is set, this is not right. We can and > should detach in this case, we only should skip utrace_reset() to > avoid the race with utrace_report_death()->REPORT_CALLBACKS(). This behavior is the original (minimal) synchronization scheme from before we had utrace_barrier. See "Interlock with final callbacks" in Documentation/DocBook/utrace.tmpl. The expectation is that your report_death is going to clean up your ->data stuff and then return UTRACE_DETACH. If utrace_control returns -EALREADY, then you know that report_death is taking care of things. I'd imagined that you'd do something like: mutex_lock(stuff engine->data points to); mark in there that we are detaching; ret = utrace_control(task, engine, UTRACE_DETACH); if (ret == 0) { /* detached. tear our stuff down. */ ... return DONE; } else if (ret == -EALREADY) { /* report_death is running, i.e. waiting for our lock */ mutex_unlock(...); return DONE; } else ... Put another way, you can have told your report_death beforehand that it should return UTRACE_DETACH if it runs before your utrace_control call. Thanks, Roland From roland at redhat.com Tue Aug 17 00:51:51 2010 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Aug 2010 17:51:51 -0700 (PDT) Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: Oleg Nesterov's message of Monday, 16 August 2010 17:09:39 +0200 <20100816150939.GA8842@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> Message-ID: <20100817005151.882C74007E@magilla.sf.frob.com> > Whatever we do, start_callback() can see the old engine->flags but > the new ->ops = &utrace_detached_ops. Just suppose that the caller > of UTRACE_DETACH is interrupted right after setting engine->ops. * it can check the old flags before using the old ops, or check the old * flags before using the new ops, or check the new flags before using the * new ops, but can never check the new flags before using the old ops. > Or do you think I miss something and this is false alarm? * Hence, utrace_detached_ops might be used with any old flags in place. * It has report_quiesce() and report_reap() callbacks to handle all cases. report_reap is covered with the utrace_detached_reap() stub. Every other callback uses start_callback(), i.e. calls report_quiesce first. utrace_detached_quiesce() returns UTRACE_DETACH, so start_callback() will return NULL. > [...] but I can no longer think properly today. Sleep well. :-) Thanks, Roland From hoops at mydestiny.net Tue Aug 17 01:47:01 2010 From: hoops at mydestiny.net (ni) Date: Tue, 17 Aug 2010 09:47:01 +0800 Subject: =?gb2312?B?0NBg1f65pCDX982zILPvudxfwO3KtV+y2bDg?= Message-ID: <20100817094711565007@mydestiny.net> (??$??%_??#??@??&??*??%??$??) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ?-?-?-?-?-?-?-?-?-?-?01.doc Type: application/msword Size: 40448 bytes Desc: not available URL: From oleg at redhat.com Tue Aug 17 11:55:34 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Aug 2010 13:55:34 +0200 Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case In-Reply-To: <20100817001308.D335D4007E@magilla.sf.frob.com> References: <20100814023128.GA9236@redhat.com> <20100817001308.D335D4007E@magilla.sf.frob.com> Message-ID: <20100817115534.GA30214@redhat.com> On 08/16, Roland McGrath wrote: > > > - It is possible that both ->death and ->reap are true. In this > > case it is OK to clear UTRACE_EVENT(REAP), but set_events fails. > > No, it's not OK to clear it. Once ->reap is set, then the engine's > ops->report_reap might or might not have been called already. Afaics - no. If utrace->death is set (and we check it under utrace->lock) we can ignore utrace->reap. In short, if ops->report_reap can be called before ->death is cleared, then 2 possible callers of utrace_maybe_reap() can race with each other, but this can't happen. utrace->death == T means: - (utrace_flags & _UTRACE_DEATH_EVENTS) == T - utrace->death was set by utrace_report_death() which will take utrace->lock later and clear ->death, only then it may call ops->report_reap(). - until utrace_report_death() clears ->death, _UTRACE_DEATH_EVENTS must be set in ->utrace_flags, otherwise utrace_maybe_reap(true) is buggy. Note that both utrace->death and _UTRACE_DEATH_EVENTS are cleared "atomically" from utrace->lock pov. IOW. utrace->death is true, then IF (utrace->reap) tracehook_prepare_releas()->utrace_maybe_reap(true) was already called, this is how utrace->reap was set. But utrace_maybe_reap() did nothing and returned. We rely on the subsequent utrace_maybe_reap(false) from utrace_report_death() - but this can't happen until we drop utrace->lock ELSE utrace->reap can't be set until we drop utrace->lock. Now that you merged c93fecc925ea7567168f0c94414b9021de2708c5 "get_utrace_lock() must not succeed if utrace->reap == T", this becomes a bit off-topic. However, I thought about relaxing the "dead" check in get_utrace_lock(), instead of utrace->reap we could check "utrace->reap && !utrace->death". In fact, initially I was going to do this, but then decided to make the simpler patch for now. Oleg. From oleg at redhat.com Tue Aug 17 12:38:51 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Aug 2010 14:38:51 +0200 Subject: [PATCH 2/4] utrace_set_events: consolidate "setting _UTRACE_DEATH_EVENTS" checks In-Reply-To: <20100817000054.6C9424007E@magilla.sf.frob.com> References: <20100814023126.GA9233@redhat.com> <20100816151946.GA9352@redhat.com> <20100817000054.6C9424007E@magilla.sf.frob.com> Message-ID: <20100817123851.GA31759@redhat.com> On 08/16, Roland McGrath wrote: > > > In short: this double check allows to avoid tasklist when utrace_flags > > already has these bits while engine->flags doesn't. > > > > But multitracing is unlikely case, in the likely case if we add > > _UTRACE_DEATH_EVENTS to engine->flags we set these bits in utrace_flags > > too. I think it makes sense to consolidate these checks to make the > > code a bit more understandable. > > I don't really agree about "unlikely case". In many uses, the systemtap > task-finder will have a utrace engine on every task in the system, for > example. Moreover, this is an importantly distinct particular kind of > micro-optimization to be doing here: avoiding a system-wide lock. Any > place that we take tasklist_lock at all, we are introducing a system-wide > slowdown or limitation on scaling, just because of our tracing of one task. > So optimizing the minimize that is qualitatively different and really much > more important than avoiding taking the utrace lock, for example. > > But with that note in your mind, I am happy to take this patch now as a > simplification and let reoptimization come back later. OK, agreed. Oleg. From oleg at redhat.com Tue Aug 17 14:27:51 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Aug 2010 16:27:51 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100817005151.882C74007E@magilla.sf.frob.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> Message-ID: <20100817142751.GA9649@redhat.com> On 08/16, Roland McGrath wrote: > > > Whatever we do, start_callback() can see the old engine->flags but > > the new ->ops = &utrace_detached_ops. Just suppose that the caller > > of UTRACE_DETACH is interrupted right after setting engine->ops. > > * it can check the old flags before using the old ops, or check the old > * flags before using the new ops, or check the new flags before using the > * new ops, but can never check the new flags before using the old ops. > > > Or do you think I miss something and this is false alarm? > > * Hence, utrace_detached_ops might be used with any old flags in place. > * It has report_quiesce() and report_reap() callbacks to handle all cases. > > report_reap is covered with the utrace_detached_reap() stub. Every other > callback uses start_callback(), i.e. calls report_quiesce first. > utrace_detached_quiesce() returns UTRACE_DETACH, Assuming ->report_quiesce() will be called. Suppose that, say, engine->flags == UTRACE_EVENT(EXEC) (no QUIESCE). 1. start_callback() reads want = engine->flags (== EXEC) 2. mark_engine_detached() sets engine->ops = &utrace_detached_ops 3. start_callback() gets ops = utrace_detached_ops After that start_callback() skips "if (want & UTRACE_EVENT(QUIESCE))" block and returns utrace_detached_ops, utrace_detached_ops->report_exec == NULL will be called. But this is minor. Roland, I can't explain this, but I have the strong gut feeling there is something else we should worry about. I am still reading this code... Oleg. From oleg at redhat.com Tue Aug 17 16:50:46 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Aug 2010 18:50:46 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100817142751.GA9649@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> Message-ID: <20100817165046.GA16253@redhat.com> On 08/17, Oleg Nesterov wrote: > > Suppose that, say, engine->flags == UTRACE_EVENT(EXEC) (no QUIESCE). > > 1. start_callback() reads want = engine->flags (== EXEC) > > 2. mark_engine_detached() sets engine->ops = &utrace_detached_ops > > 3. start_callback() gets ops = utrace_detached_ops > > After that start_callback() skips "if (want & UTRACE_EVENT(QUIESCE))" block > and returns utrace_detached_ops, utrace_detached_ops->report_exec == NULL > will be called. OK, instead of filling utrace_detached_ops{} we can change start_callback() - if (want & UTRACE_EVENT(QUIESCE)) { + if ((want & UTRACE_EVENT(QUIESCE)) || ops == detached_ops) { > But this is minor. Roland, I can't explain this, but I have the strong > gut feeling there is something else we should worry about. I am still > reading this code... Or not... I'll recheck once again tomorrow and try to make the patch. In particular, I'd like to think if we can simplify this somehow. Say, avoid the barriers somewhere, or avoid changing engine->flags in mark_engine_detached(). I am worried that mark_engine_detached() sets engine->flags, but it doesn't add QUIESCE to utrace_flags. I can't convince myself that utrace_do_stop() closes all possible races. And, in particular, I don't understand this code in utrace_get_signal: } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { /* * We only got here to clear utrace->signal_handler. */ return -1; } How so? What if we were called because of utrace_control(INTERRUPT) and QUIESCE is not set? Oleg. From oleg at redhat.com Tue Aug 17 17:35:42 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Aug 2010 19:35:42 +0200 Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction In-Reply-To: <20100817004443.D95244007E@magilla.sf.frob.com> References: <20100816093929.GA24436@redhat.com> <20100817004443.D95244007E@magilla.sf.frob.com> Message-ID: <20100817173542.GA20692@redhat.com> On 08/16, Roland McGrath wrote: > > > The problem is, utrace_control(DETACH) does nothing and returns > > -EALREADY if utrace->death is set, this is not right. We can and > > should detach in this case, we only should skip utrace_reset() to > > avoid the race with utrace_report_death()->REPORT_CALLBACKS(). > > This behavior is the original (minimal) synchronization scheme from before > we had utrace_barrier. See "Interlock with final callbacks" in > Documentation/DocBook/utrace.tmpl. OK, I agree my patch breaks this part Normally utrace_control called with UTRACE_DETACH returns zero, and this means that no more callbacks will be made. of documentation (which I never read ;) > The expectation is that your report_death is going to clean up your ->data > stuff and then return UTRACE_DETACH. If utrace_control returns -EALREADY, > then you know that report_death is taking care of things. I'd imagined > that you'd do something like: > > mutex_lock(stuff engine->data points to); > mark in there that we are detaching; > ret = utrace_control(task, engine, UTRACE_DETACH); > if (ret == 0) { > /* detached. tear our stuff down. */ > ... > return DONE; > } else if (ret == -EALREADY) { > /* report_death is running, i.e. waiting for our lock */ > mutex_unlock(...); > return DONE; Sure, it is possible to do something to overcome the problem. However, at least for ugdb this means the nasty, nasty, nasty and otherwise unnecessary complications. Say, this immediately leads to refcounted ugdb_process. Or we need more data in ugdb_thread. But in any case, personally I dislike the current behaviour anyway, I think this certainly complicates the life for module writers. Instead of simple detach + barrier, you always need the nontrivial code if report_quiesce/death ever touches engine->data! This can't be good. All I can say - I need to think more. utrace_barrier() needs changes anyway (damn, not today again). If utrace_control(DETACH) treats utrace_report_death() specially and requires we must not race with its reporting loop, then probably utrace_barrier() could take ->death into account too. Or, better, I'll try to do a slightly different patch which doesn't break the documented behaviour. Oleg. From vertexes at spidermd.com Tue Aug 17 20:03:29 2010 From: vertexes at spidermd.com (Grippi Belcourt) Date: Tue, 17 Aug 2010 22:03:29 +0200 Subject: Your wife photos attached Message-ID: <4C6AEA87.4070106@spidermd.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: raveled.zip Type: application/octet-stream Size: 11296 bytes Desc: not available URL: From xjm at qdxi.com Wed Aug 18 07:48:37 2010 From: xjm at qdxi.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Wed, 18 Aug 2010 07:48:37 -0000 Subject: =?GB2312?B?QjZ1dHJhY2UtZGV2ZWy197jatffQvbywzqW8zdSxuaS0psDt?= Message-ID: <201008180748.o7I7mBpD002498@mx1.redhat.com> utrace-devel?????????????????????????? ?????2010?8?20-21? ?? ?????2010?8?27-28? ?? ?????2000/?????????????????? ????????????????????????/??/??????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? ====================================================================================== ?????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????? --------------------------------------------------------------------------------- ????????????????????????????????????????10 ?????????????????????????????????????????? ????????????????????????????????????????? ???????? --------------------------------------------------------------------------------- ???? ???10?????? ????????????????????? 1. ?????????????????????? 2. ????????????????????????????????? 3. ????????????????????????? 4. ?????????????????90%???????????? 5. ??????????????????? 6. ???????????????????? 7. ?????????????????? 8. ???????????????????? 9. ????????????????????? 10. ??????????? 11. ???????????????????? 12. ?????????????????? 13. ???????????? ?????????????????????? 1. ????????????????????? 2. ???????????????????????? 3. ??????????????????95%???????????? 4. ???????????????????? 5. ????????????????? 6. ??????????????????? 7. ????????????????????????? 8. ?????????????????70%?????? 9. ???????????????????????????????????????? ??50%?????????? 10. ??????????????????????????? 11. ?????????????????????????? 12. ???????????????????? 13. ?????????????????????????? ???????????????? 1. ????????????????????????????? 2. ????????????????????????? 3. ???????????????80%???????????? 4. ????????????????? 5. ???????????????? 6. ????????????????????? 7. ????????????????????? 8. ????????????????? 9. ???????????????????? 10. ??????????? 11. ??????????????????????? ?????????????????????? 1. ????????????????????? 2. ????????????????????????? 3. ?????????????????80%???????????? 4. ??????????????????? 5. ??????????????????? 6. ????????????????????????????????????????? 7. ?????????????????????????? 8. ???????????????? 9. ??????????????????????????????? 10. ??????????????????????????????????????? ?????????????????????? ???????????????? 1. ?????????????? 2. ??????????????????????? 3. ???????????????? 4. ???????????? 5. ???????????? 6. ?????????????? 7. ???????????????????? 8. ?????????????????? 9. ????????????? 10. ??????????????????????? 11. ?????????????????????? 12. ??????????????????? 13. ????????????????? 14. ?????????????????? ????????????????????????????? 1. ?????????? 2. ???????????? 3. ???????????????? 4. ??????????????????? 5. ??????????? ?????????????????????? ---------------------------------------------------------------------------- ?????????????????????????????????????????? ????????????????????? ????????????????????????????????????????? ?????????2007????????????????????????????95%? ????????????????????????????????????????? ?????????????????07???????????300????????1500? ?????????95%????????????1300???????????????? ?????????????????????????????????????????? ??????????????????????????????????????1000? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ?????????????????????????????????????????? ????????????????????????SONY??????????????PHILIP? ???????????????????????????????????????????? ??????????HP????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????TCL???????? ------------------------------------------------------------------------------- ?????????????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From e-bulten at mpsglobalexpress.com Tue Aug 17 19:58:39 2010 From: e-bulten at mpsglobalexpress.com (=?UTF-8?B?TXBzIFJ1c3lhICYgVMO8cmtpIEN1bWh1cml5ZXRsZXIgSMSxemzEsSBQYWtldCBUYcWfxLFtYQ==?= =?UTF-8?B?Y8SxbMSxxJ/EsSBBLsWe?=) Date: Tue, 17 Aug 2010 22:58:39 +0300 Subject: =?UTF-8?B?RMO8bnlhbsSxbiBIZXJ5ZXJpbmUgSMSxemzEsSB2ZSBFa29ub21payBIYXZhIEthcmdvICYg?= =?UTF-8?B?S3VyeWUgVGHFn8SxbWFjxLFsxLHEn8SxIA==?= Message-ID: <201008181135.o7IBZr83002417@mx1.redhat.com> MPS Express Dev Kampanya.... MPS Gift Hediye Kampanyas?ndan Sizde Yararlan?n... D?nyan?n 220 ?lkesinde Faliyet g?steren MPS Express T?rkiyeden D?nyan?n Heryerine D?k?man Paket Koli ve ?hracat Kargolar?n?z? en h?zl? en ekonomik ve en g?venli ?ekilde ta??ma hizmetini bir yenisini daha ekledi.T?rkiyeden Rusya ve Ukrayna ?lkelerine g?nderece?iniz her t?rl? kargolar?n?z? kg g?zetmeksizin KAPIDAN - KAPIYA ?mza kar??l??? teslim ederek rakipsiz bir hizmet ba?latm??t?r. Rusya & Ukrayna Paket Ta??mac?l??? Var?? ?lkesinde g?mr??e tabi olsun olmas?n numunelerinizi Rusya ve Ukrayna ?lkelerinde Rakipleri G?mr??e b?rak?rken,MPS Express M??terinizin kap?s?na teslim etmeyi taah?t ediyor. Rusya ve Ukrayna Fuar Ta??ma Hizmeti MPS Express Fuar Ta??ma hizmeti ile kat?laca??n?z fuarlarda organizasyonlar?n?z?n ba?ar? ile sonu?land?rman?za yard?mc? olmak i?in sizi sadece sat?? odakl? k?labilmek ve kat?laca??n?z etkinlik nerede olursa olsun MPS Express KAL?TE VE DENEY?M? VE HIZLI. Sizlere tam zamanl? organizasyonlar?n?z?n her a?amas?nda ?stlenerek m??terileriniz ile 10.y?l?nda bulu?turma devam ediyor... D?nyan?n Heryerine H?zl? ve Ekonomik Hava Kargo & Kurye Ta??mac?l??? MPS Express Yurtd???na g?nderece?iniz T?m Kargolar?n?zda D?nyan?n 220 ?lkesine H?zl? & Ekonomik g?venilir bir ?ekilde ta??ma hizmeti sa?lamaktad?r.D?nya ?ap?nda bir ?ok g??l? kurulu? ile i?birli?i yapan MPS Express T?rkiye genelinde M??terilerine sundu?u kaliteli hizmet sayesinde 220 ?lke ve ?zerk b?lgede konumunu s?rd?rmektedir.MPS Express ?e?itli ?lkeler de en yayg?n kurulu?lar i?birli?i yapmay? tercih ederek m??terilerine lokal da??t?mda en da??t?m firmalar? ile ?al??ma avantajlar? sa?lamaktad?r. Hava Kargo T?rkiyeden D?nyan?n her yerine ,D?nyan?n her yerinden Havaliman? yada kap?dan kap?ya havayolu ta??mac?l??? hizmetleri veren MPS Express Se?kin havayolu ?irketleri ile Yap?lan anla?malar sayesinde ta??malarda yer ve fiyat avantajlar? sa?lamaktad?r.MPS Express Sekt?r?nde deneyimi ve ?al??ma anlay??? ile havayolu ta??mac?l???nda T?rkiyede ?nc? bir marka haline gelmi?tir.?hracatta artan d?? rekabetin ve uluslararas? arenadaki al?c?lar?n daha h?zl? termin isteklerinin sonucu olarak olu?an kalite hizmet ve ekonomik ??z?mler ile talebini kar??layarak yat?r?mlar?n? tamamlam??t?r. D?nyan?n Heryerine Hava Kargo ?r?n ve Hizmetlerimiz M??teri Hizmetleri .:+ 90 212 444 0 108 Havaliman?ndan Havaliman? Ta??ma ??z?mleri sales at mpsglobalexpress.com www.mpsglobalexpress.com Havaliman?ndan Kap?ya Ta??ma ??z?mleri info at mpsglobalexpress.com Tehlikeli Madde Ta??ma ??z?mleri Kap?dan Havaliman?na Ta??ma ??z?mleri Kap?dan Kap?ya Ta??ma ??z?mleri G?mr?kl? & G?mr?ks?z Kap? Teslimi Yolcu beraberinde Kargo Teslim ??z?mleri Rusya ve Ukrayna Acil Kargo ??z?mleri - -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Aug 18 13:48:03 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Aug 2010 15:48:03 +0200 Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction In-Reply-To: <20100817173542.GA20692@redhat.com> References: <20100816093929.GA24436@redhat.com> <20100817004443.D95244007E@magilla.sf.frob.com> <20100817173542.GA20692@redhat.com> Message-ID: <20100818134803.GA21031@redhat.com> On 08/17, Oleg Nesterov wrote: > > On 08/16, Roland McGrath wrote: > > > > > The problem is, utrace_control(DETACH) does nothing and returns > > > -EALREADY if utrace->death is set, this is not right. We can and > > > should detach in this case, we only should skip utrace_reset() to > > > avoid the race with utrace_report_death()->REPORT_CALLBACKS(). > > > > This behavior is the original (minimal) synchronization scheme from before > > we had utrace_barrier. See "Interlock with final callbacks" in > > Documentation/DocBook/utrace.tmpl. > > OK, I agree my patch breaks this part > > Normally > utrace_control called with > UTRACE_DETACH returns zero, and this means that no > more callbacks will be made. > > of documentation (which I never read ;) Wait. It doesn't break this. It only breaks -EALREADY contract. And I don't understand why this is bad. > But in any case, personally I dislike the current behaviour anyway, > I think this certainly complicates the life for module writers. > Instead of simple detach + barrier, you always need the nontrivial > code if report_quiesce/death ever touches engine->data! This can't > be good. Yes. Roland, could you explain once again why do you dislike this patch? Once again. Currently utrace_control(DETACH) refuses to even try to detach the engine if utrace->death is set. Why? What is the point? What makes UTRACE_EVENT(DEATH) so special? I do not see the logic at all. If ->report_death() does something which the caller of utrace_control() should know, then they should take care of synchronization anyway. With or without this patch, utrace_control(DEATH) can return 0 after ->report_death() was already called. Currently, utrace_control(DETACH) returns -EALREADY when this callback was alredy called, or it can be called later, or it may be running. And utrace_barrier() can't help. With this patch utrace_control(DETACH) returns either 0 with the same meaning (will not be called later, but probably was already called before utrace_control), or -EINPROGRESS which suggests to use utrace_barrier(). Please correct me, but I think this certainly makes things much simpler. Otherwise UTRACE_DETACH is never trivial (and iiuc it is better to avoid utrace_engine_ops->release() hook). What do you think? Oleg. From zhanghui8 at 188.com Wed Aug 18 14:37:29 2010 From: zhanghui8 at 188.com (=?gbk?B?1cW71A==?=) Date: Wed, 18 Aug 2010 22:37:29 +0800 (CST) Subject: =?gbk?B?zbXX39XiM7j2w9i+9y4uLi7Iw8Tjy6++9ba8v8nS1C4u?= =?gbk?B?Li4utLTU7NS01LSyu7bPtcTK1cjrLi4uLi4uLi4u?= Message-ID: <13d916f.de0a.12a85a22105.Coremail.zhanghui8@188.com> ?????? ????????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????????45???????????????????????????????????????????????????11????????????????????????45???????????????????????? ????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? ???????????????????? NO NO NO ??? ??????????? ???????????????????100%???? ???????????????? 1????3????248???????? 2?????????????????????? 3?7??????????????????? ? 4?????????????????????????????? 5????3???????????????14???1000????240000? ? 6?????????????????? ??????????? 7????????????????????????????????? 8?9????????? ???????????????????? ????????? ????????????????????????????????????????????????? ??????????????????????????????? ??????????????????????? ?????????????????????????????????? ???????????2??????????????????? ???????????? ???24???????400--6868---772???? ???????????????????????13564693672 ???????????????????????? ????????? ????????????????????????? ps????????3?????????????????????48????? ???????????????????????????????????????????????????????????????????? www.yingxiaomijue.com PPS???????????????????????????100??????????????????????50?????????????72???????????????? PPPS?????????????????????????????72??????????????????????? PPPPS???????????????????????????????????????????????????????????????????????????????1000?????? ??: www.yingxiaomijue.com ?????13564693672 QQ:694288858 -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Aug 18 16:32:33 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Aug 2010 18:32:33 +0200 Subject: [PATCH] fix mark_engine_detached() vs start_callback() race Message-ID: <20100818163233.GA31062@redhat.com> Suppose that engine->flags == UTRACE_EVENT(EXEC), QUIESCE bit is not set. 1. start_callback() reads want = engine->flags (== EXEC) 2. mark_engine_detached() sets engine->ops = &utrace_detached_ops 3. start_callback() gets ops = utrace_detached_ops After that start_callback() skips "if (want & UTRACE_EVENT(QUIESCE))" block and returns utrace_detached_ops, then ->report_exec == NULL will be called. This is the minimal temporary ugly fix for now, we should certainly cleanup and simplify this logic. The barriers in mark_engine_detached() and in start_callback() can't help and should be removed. If we ignore utrace_get_signal() we do not even need utrace_detached_quiesce(), start_callback() could just do ops = engine->ops; if (ops == utrace_detached_ops) { report->detaches = true; return NULL; } I think in the longer term mark_engine_detached() should not change engine->flags at all but add QUIESCE to ->utrace_flags. However, this breaks utrace_maybe_reap(reap => true) and we should avoid the race with finish_callback() which clears ->reporting after report_quiesce(). A bit off-topic, but I don't think finish_callback() should check engine->ops == &utrace_detached_ops before return. Instead we should change finish_callback_report() to return the boolean. We shouldn't return true without setting report->detaches. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- kstub/kernel/utrace.c~8_fix_mark_detached_without_quiesce 2010-08-18 16:46:08.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-18 17:47:53.000000000 +0200 @@ -1522,7 +1522,7 @@ static const struct utrace_engine_ops *s smp_rmb(); ops = engine->ops; - if (want & UTRACE_EVENT(QUIESCE)) { + if ((want & UTRACE_EVENT(QUIESCE)) || ops == &utrace_detached_ops) { if (finish_callback(task, utrace, report, engine, (*ops->report_quiesce)(report->action, engine, event))) From oleg at redhat.com Wed Aug 18 17:27:04 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Aug 2010 19:27:04 +0200 Subject: [PATCH] utrace_barrier(detached_engine) must not sping without checking ->reporting Message-ID: <20100818172704.GA2230@redhat.com> If engine is detached (has utrace_detached_ops), utrace_barrier(engine) spins until engine->ops becomes NULL. This is just wrong. Suppose that utrace_control(DETACH) returns -EINPROGRESS, now we should call utrace_barrier(). However, it is possible that -EINPROGRESS means we raced with sys_sleep(A_LOT) doing report_syscall_entry(). Or it could race with any callback, but another engine requested UTRACE_STOP. If start_callback() notices utrace_detached_ops and sets report->detaches everything is fine. But it is quite possible that this doesn't happen, and in this case utrace_barrier() will spin "forever" waiting for the next utrace_reset(). Change get_utrace_lock() to succeed if the caller is utrace_barrier() and ops == &utrace_detached_ops. I do not see any reason why this case should be special from utrace_barrier's pov. It can just check ->reporting and return 0 or do another iteration. Note: we should also reconsider() utrace_barrier()->signal_pending() check. Also, it is not clear why utrace_barrier() needs utrace->lock, except to ensure it is safe to dereference target/utrace. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) --- kstub/kernel/utrace.c~9_utrace_barrier_and_detached 2010-08-18 17:47:53.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-18 19:00:50.000000000 +0200 @@ -416,23 +416,21 @@ static struct utrace *get_utrace_lock(st return ERR_PTR(-ESRCH); } - if (unlikely(engine->ops == &utrace_detached_ops)) { + if (!attached && unlikely(engine->ops == &utrace_detached_ops)) { rcu_read_unlock(); - return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); + return ERR_PTR(-ESRCH); } utrace = task_utrace_struct(target); spin_lock(&utrace->lock); if (unlikely(utrace->reap) || unlikely(!engine->ops) || - unlikely(engine->ops == &utrace_detached_ops)) { + (!attached && unlikely(engine->ops == &utrace_detached_ops))) { /* * By the time we got the utrace lock, * it had been reaped or detached already. */ spin_unlock(&utrace->lock); utrace = ERR_PTR(-ESRCH); - if (!attached && engine->ops == &utrace_detached_ops) - utrace = ERR_PTR(-ERESTARTSYS); } rcu_read_unlock(); @@ -1286,8 +1284,7 @@ int utrace_barrier(struct task_struct *t utrace = get_utrace_lock(target, engine, false); if (unlikely(IS_ERR(utrace))) { ret = PTR_ERR(utrace); - if (ret != -ERESTARTSYS) - break; + break; } else { /* * All engine state changes are done while From oleg at redhat.com Wed Aug 18 18:11:47 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Aug 2010 20:11:47 +0200 Subject: [PATCH?] avoid the unnecessary utrace_resume()->utrace_reset() Message-ID: <20100818181147.GA4995@redhat.com> utrace_resume(UTRACE_REPORT) always calls utrace_reset() because start_callback() obviously can't clear report->spurious when event == 0. Change start_callback() to correctly clear ->spurious in this case. We could probably clear it in utrace_resume() unconditionally after reporting loop, but this is not exactly right if there are no engines which have QUIESCE in engine->flags. utrace_get_signal() probably has the same problem. Note: utrace_control(DETACH) does utrace_do_stop() and sets UTRACE_REPORT if the tracee is not stopped. It also does mark_engine_detached() which does not set QUIESCE in target->utrace_flags. This means we rely on report.spurious which should provoke utrace_reset() from utrace_resume() if target->utrace_flags doesn't have QUIESCE. A bit too subtle, imho. Also, UTRACE_REPORT can be lost because of UTRACE_INTERRUPT or normal signal: utrace_get_signal() checks "utrace_flags & UTRACE_EVENT(QUIESCE)" and returns otherwise. This should be fixed somehow. This check is wrong anyway, but it is not clear how we can fix the race with DETACH. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- kstub/kernel/utrace.c~10_utrace_resume_and_spurious 2010-08-18 19:00:50.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-18 19:41:05.000000000 +0200 @@ -1540,7 +1540,7 @@ static const struct utrace_engine_ops *s if (want & ENGINE_STOP) report->action = UTRACE_STOP; - if (want & event) { + if (want & (event ?: UTRACE_EVENT(QUIESCE))) { report->spurious = false; return ops; } From unclear at accthome.com Thu Aug 19 13:23:03 2010 From: unclear at accthome.com (Bartolomei Calcote) Date: Thu, 19 Aug 2010 15:23:03 +0200 Subject: Your wife photos attached Message-ID: <4C6D2FB5.7030202@accthome.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: whipcord.zip Type: application/octet-stream Size: 11817 bytes Desc: not available URL: From oleg at redhat.com Thu Aug 19 13:56:38 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Aug 2010 15:56:38 +0200 Subject: [PATCH v2] utrace_barrier(detached_engine) must not sping without checking ->reporting In-Reply-To: <20100818172704.GA2230@redhat.com> References: <20100818172704.GA2230@redhat.com> Message-ID: <20100819135638.GA2230@redhat.com> On 08/18, Oleg Nesterov wrote: > > If engine is detached (has utrace_detached_ops), utrace_barrier(engine) > spins until engine->ops becomes NULL. This is just wrong. > > Suppose that utrace_control(DETACH) returns -EINPROGRESS, now we should > call utrace_barrier(). However, it is possible that -EINPROGRESS means > we raced with sys_sleep(A_LOT) doing report_syscall_entry(). Yes, > Or it could > race with any callback, but another engine requested UTRACE_STOP. No, this is not possible, utrace_stop() must never sleep with just-detached-engine. > if (unlikely(utrace->reap) || unlikely(!engine->ops) || > - unlikely(engine->ops == &utrace_detached_ops)) { > + (!attached && unlikely(engine->ops == &utrace_detached_ops))) { Oh, I confused attached and !attached. Noticed this only because I hit the "new" problems with utrace during the testing ;) Please find v2 below. ------------------------------------------------------------------------------- [PATCH v2] utrace_barrier(detached_engine) must not sping without checking ->reporting If engine is detached (has utrace_detached_ops), utrace_barrier(engine) spins until engine->ops becomes NULL. This is just wrong. Suppose that utrace_control(DETACH) returns -EINPROGRESS, now we should call utrace_barrier(). However, it is possible that -EINPROGRESS means we raced with, say, sys_sleep(A_LOT) doing report_syscall_entry(). If start_callback() notices utrace_detached_ops and sets report->detaches everything is fine. But it is quite possible that this doesn't happen, and in this case utrace_barrier() will spin "forever" waiting for the next utrace_reset(). Change get_utrace_lock() to succeed if the caller is utrace_barrier() and ops == &utrace_detached_ops. I do not see any reason why this case should be special from utrace_barrier's pov. It can just check ->reporting and return 0 or do another iteration. Note: we should also reconsider() utrace_barrier()->signal_pending() check. Also, it is not clear why utrace_barrier() needs utrace->lock, except to ensure it is safe to dereference target/utrace. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) --- kstub/kernel/utrace.c~9_utrace_barrier_and_detached 2010-08-18 17:47:53.000000000 +0200 +++ kstub/kernel/utrace.c 2010-08-19 15:33:06.000000000 +0200 @@ -416,23 +416,21 @@ static struct utrace *get_utrace_lock(st return ERR_PTR(-ESRCH); } - if (unlikely(engine->ops == &utrace_detached_ops)) { + if (attached && unlikely(engine->ops == &utrace_detached_ops)) { rcu_read_unlock(); - return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); + return ERR_PTR(-ESRCH); } utrace = task_utrace_struct(target); spin_lock(&utrace->lock); if (unlikely(utrace->reap) || unlikely(!engine->ops) || - unlikely(engine->ops == &utrace_detached_ops)) { + (attached && unlikely(engine->ops == &utrace_detached_ops))) { /* * By the time we got the utrace lock, * it had been reaped or detached already. */ spin_unlock(&utrace->lock); utrace = ERR_PTR(-ESRCH); - if (!attached && engine->ops == &utrace_detached_ops) - utrace = ERR_PTR(-ERESTARTSYS); } rcu_read_unlock(); @@ -1286,8 +1284,7 @@ int utrace_barrier(struct task_struct *t utrace = get_utrace_lock(target, engine, false); if (unlikely(IS_ERR(utrace))) { ret = PTR_ERR(utrace); - if (ret != -ERESTARTSYS) - break; + break; } else { /* * All engine state changes are done while From pn at uwqg.com Thu Aug 19 17:37:07 2010 From: pn at uwqg.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Fri, 20 Aug 2010 01:37:07 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsvbW1zbLJubqzybG+vLC5qdOmyczMuMXQ?= Message-ID: <201008191737.o7JHapp8003155@mx1.redhat.com> utrace-devel?????????????? ?????2010?8?24-25? ?? ?????2010?9?4-5? ?? ?????2010?9?7-8? ?? ?????2010?10?9-10? ?? ?????????2500?/?????????????????? ????? ?????????????????????????????????. ???????600?/?;??800?/?(??????????????) ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ????? ?????????????????????? ????????????????????????????? ?????????????? ???????????????? ????????????? ??????????? ------------------------------------- ????? ?????????????? ????????????? ??????????? ????????????????? ??????????????? ??????????????? ?????????? ?????????? ????????? ------------------------------------- ???? ?????????????????? ??????????????? ?????KPI?????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ????????????? ????????????? ???? ?????? ?????? ???? ??????????????? ??????????????? XX??2009?????? ??????????? ?????????? ?????????????? ?????????? ????????????????? ????????????? ??????? ????????????? ???????????? ??????????? ??????????????? ?????????????? ???????????? ????????? ????????? ??????? ?????????????????? ??????????? ?????-??????? ????? ????????????? ?????????? ??????? ?????????????? ?????????? ??????????? ??????????????? ?????????? ????????(???)???? ???????????? ????????????? ?????????? ?????????? ??????? ?????? ??????????? ??????????????????? ??????? ?????????????? ????? ??????????????? ?????? ???????????????? ????????????? ?????????? ?????????????? ??????????? ???????????????? ??????????? ??????????? ?????????????? ??????????????? ?????????????????? ??????????? ??????????? ??????? ?????????????? ???? ???? ??????? ?????????? ???????? ??????????? ???????? ??????? ?????????? ????????? ?????????????? ??(??)??????? ???????????? ??????????? ????????? ???????? ?????????? ????????? ???????????????? ??????????? ???????????? ?????? ??????? ?????????? ???????? ????????? ????? ???????????? ????????????????????? ???????????? ??????? ?????????? ???????????? ??????????? ???????????? ????????? ?????????? ?????????????? ??????????? ????? ???????? ???? ?????????? ???????? ???????? ??????? ??????????????? ????????????? ??????????? ???????? ??????????? ?????????????????? ??????????????? ?????KPI?????? ??????????? ?????????????? ???????? ????? ???????????????? ?????? ????????????????? ??????????? ??????????? ????????????? ???Pareto(???)??? ABC??? ???????????????? ??????????????? ??????????????? ????????????? ????????????ff ?????????? ???????? ????????????? ?????????????? ?????????????? ????????VMI?? ???JIT???? ???????????? ??????? ???JIT? JIT?JIC??? JIT?????JIT??????? ?????????? ???????????? ??????? (VMI) ?????? ?????? ------------------------------------------------------------------------------ ??????????? 1986????Gerber?????????Michigan State University (???????) ????????????,?????Heinz(??)??????????????????????????? ?????????????????????????????2000???,???????????????? ?????????,???????500??????????????,?????????????????? ??????????????????????????????????????????????????? ??????????? ??????????????????????????????????????? ?????????????????????????????????????????????????? ????? ?????????????,?????????,??,???????????,?????,?? ???????????????????????????????,??????????????,???? ????????????????? ---------------------------------------------------------------------------------------------- ????? ????????????020-62351156 ??????? ????? 2010?___________ ? ______ ??? ??????????????? ??????????????????????????????????????????? ??????????????? ?????????????? ????????????? ????????????????? ??????????????????????? ????????? ? ??????????? ? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? From oleg at redhat.com Thu Aug 19 17:49:55 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Aug 2010 19:49:55 +0200 Subject: gdbstub initial code, v4 Message-ID: <20100819174955.GA14618@redhat.com> Changes: Only internal cleanups. I was busy with utrace fixes and testing. With utrace patches I sent, I do not see any problems so far. But utrace definitely needs more changes. Next step: handle exit correctly and report W/S. I misunderstood what gdbserver does when the main thread exits, it is not stupid as I wrongly thought. Note the second attachment, GDBCAT. It is just the simple perl script which connects /proc/ugdb to tcp port. It can be used for remote debugging via tcp, or with (unpatched) gdb which can't do select() on /proc/ugdb. Actually, it is more convenient to use it in any case, at least for logging purposes. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { // XXX: temporary racy check WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ struct ugdb_thread { int t_tid; int t_stop_state; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { struct task_struct *task = pid_task(thread->t_spid, PIDTYPE_PID); BUG_ON(!task); return task; } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static inline void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); ugdb_del_stopped(ugdb, thread); spin_unlock(&ugdb->u_slock); } /* NULL if called by attach */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH)); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* * Ensure a callback can't race with utrace_destroy_thread(). * If we race with ugdb_report_clone() or ugdb_report_death(), * they must see P_DETACHING under ->u_mutex. */ if (ret == -EINPROGRESS) utrace_barrier_pid(thread->t_spid, thread->t_engine); } static const struct utrace_engine_ops ugdb_utrace_ops; /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state = P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct ugdb_thread *ugdb_attach_main(struct ugdb *ugdb, struct ugdb_process *process) { struct ugdb_thread *thread; struct pid *spid; spid = find_get_pid(process->p_pid); if (!spid) return NULL; thread = ugdb_attach_thread(process, spid); if (IS_ERR(thread)) thread = NULL; put_pid(spid); return thread; } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct pid *next = NULL; task = pid_task(curr, PIDTYPE_PID); BUG_ON(!task); spin_lock_irq(&task->sighand->siglock); for (;;) { task = next_thread(task); // XXX: BUG: if main is not group leader we can race with exec if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&task->sighand->siglock); return next; } static int ugdb_attach(struct ugdb *ugdb, int pid) { struct ugdb_process *process; struct ugdb_thread *thread; struct pid *main_pid, *curr_pid; // XXX: check if exists process = ugdb_create_process(ugdb, pid); if (!process) goto err; mutex_lock(&ugdb->u_mutex); // XXX: check if group leader ? thread = ugdb_attach_main(ugdb, process); if (!thread) goto abort; main_pid = thread->t_spid; curr_pid = main_pid; for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } // XXX mark it just attached mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); ugdb_destroy_process(process); err: return -1; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); WARN_ON(thread->t_stop_state & T_STOP_ACK); if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; ret = true; thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } unlock: spin_unlock(&ugdb->u_slock); return ret; } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { /* * (gdb) interrupt & * (gbd) interrupt -a & * * make sure -a actually works if it races with clone. */ if (all && !(thread->t_stop_state & T_STOP_ALL)) { /* * We hold ugdb->u_mutex, so we can't race with * ugdb_report_clone(). But we need spinlock to * avoid the race with ugdb_add_stopped() which * can change ->t_stop_state in parallel. */ spin_lock(&ugdb->u_slock); thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); } return 0; } // XXX: currently we can do this lockless ... thread->t_stop_state = all ? (T_STOP_REQ | T_STOP_ALL) : T_STOP_REQ; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; bool is_main; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); is_main = (process->p_pid == thread->t_tid); ugdb_destroy_thread(thread); if (is_main) ; // XXX: DAMN!!! unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; const char *stop = "T00"; int pid, tid; int ret = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; pid = thread->t_process->p_pid; tid = thread->t_tid; ret = 1; unlock: mutex_unlock(&ugdb->u_mutex); if (ret) { struct pbuf *pb = &ugdb->u_pbuf; if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } pb_printf(pb, "%sthread:p%x.%x;", stop, pid, tid); pb_end(pb); } return ret; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } count = pb_copy_to_user(pb, ubuf, count); if (count > 0) *ppos += count; return count; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); *ppos += count; return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); -------------- next part -------------- #!/usr/bin/perl -w use strict; sub cat { my ($dir, $F1, $F2) = @_; for (;;) { if (!sysread $F1, $_, 4096) { return if $! == 11; #EAGAIN; print STDERR 'conn closed:', $! || 'EOF', "\n"; exit; } length == syswrite $F2, $_ or die; s/^\+//; s/^\$//; s/#..\Z//s; substr($_, 62) = '...' if length $_ > 64; print "$dir $_\n"; } } sub main_loop { my ($F1, $F2) = @_; # FIONBIO ioctl $F1, 0x5421, pack 'i!', 1 or die $!; ioctl $F2, 0x5421, pack 'i!', 1 or die $!; for (my $rfd = '';;) { vec($rfd, fileno $F1, 1) = 1; vec($rfd, fileno $F2, 1) = 1; 0 < select $rfd, undef, undef, undef or die; cat '=>', $F1, $F2 if vec $rfd, fileno $F1, 1; cat '<=', $F2, $F1 if vec $rfd, fileno $F2, 1; } } sub wait_for_connect { my $port = 0+shift; socket my $sk, 2,1,0 or return die "sock create: $!"; defined setsockopt $sk, 1,2,1 or return die "sock reuseaddr: $!"; bind $sk, pack 'Sna12', 2, $port, '' or return die "sock bind $port port: $!"; listen $sk, 2 or return die "sock listen: $!"; print "wait for connection on $port port ...\n"; accept my $conn, $sk or return die "sock accept: $!"; return $conn; } sub main { my $port = 2000; if (@_) { $port = shift; die "Usage: $0 [port]\n" if @_ || $port =~ /\D/; } my $conn = wait_for_connect $port or exit; sysopen my $ugdb, '/proc/ugdb', 2 or die 0; main_loop $conn, $ugdb; } main @ARGV; From roland at redhat.com Thu Aug 19 21:11:31 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 14:11:31 -0700 (PDT) Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case In-Reply-To: Oleg Nesterov's message of Tuesday, 17 August 2010 13:55:34 +0200 <20100817115534.GA30214@redhat.com> References: <20100814023128.GA9236@redhat.com> <20100817001308.D335D4007E@magilla.sf.frob.com> <20100817115534.GA30214@redhat.com> Message-ID: <20100819211131.9862E40080@magilla.sf.frob.com> > On 08/16, Roland McGrath wrote: > > > > > - It is possible that both ->death and ->reap are true. In this > > > case it is OK to clear UTRACE_EVENT(REAP), but set_events fails. > > > > No, it's not OK to clear it. Once ->reap is set, then the engine's > > ops->report_reap might or might not have been called already. > > Afaics - no. > > If utrace->death is set (and we check it under utrace->lock) we can > ignore utrace->reap. > > In short, if ops->report_reap can be called before ->death is cleared, > then 2 possible callers of utrace_maybe_reap() can race with each other, > but this can't happen. Right. If ->death is still set, it means utrace_report_death is still running. So the utrace internals know that the report_reap callbacks haven't started yet. But from the utrace API perspective, all you can know is that release_task() has already been called. So I think it's right for the API not to let you clear UTRACE_EVENT(REAP) at that point. > utrace->death == T means: > > - (utrace_flags & _UTRACE_DEATH_EVENTS) == T Yes. > - utrace->death was set by utrace_report_death() which will take > utrace->lock later and clear ->death, only then it may call > ops->report_reap(). Yes. > - until utrace_report_death() clears ->death, _UTRACE_DEATH_EVENTS > must be set in ->utrace_flags, otherwise utrace_maybe_reap(true) > is buggy. Yes. > Note that both utrace->death and _UTRACE_DEATH_EVENTS are cleared > "atomically" from utrace->lock pov. Yes. > IOW. utrace->death is true, then > > IF (utrace->reap) > > tracehook_prepare_releas()->utrace_maybe_reap(true) was > already called, this is how utrace->reap was set. Meaning release_task() was called--semantically "reaping may have begun". > But utrace_maybe_reap() did nothing and returned. > We rely on the subsequent utrace_maybe_reap(false) from > utrace_report_death() - but this can't happen until > we drop utrace->lock Correct. > ELSE > utrace->reap can't be set until we drop utrace->lock. Correct. > Now that you merged c93fecc925ea7567168f0c94414b9021de2708c5 > "get_utrace_lock() must not succeed if utrace->reap == T", this becomes > a bit off-topic. However, I thought about relaxing the "dead" check in > get_utrace_lock(), instead of utrace->reap we could check > "utrace->reap && !utrace->death". In fact, initially I was going to > do this, but then decided to make the simpler patch for now. When utrace->reap is set, it means release_task() has been called. The API caller has no way to know reaping hasn't already begun--except if its report_death callback has not returned yet. But I think that the API definition of "once release_task() has been called (i.e. entered, maybe not returned yet), any utrace call will get -ESRCH", is a clear and comprehensible constraint. We should not open any holes in that. Thanks, Roland From ri at fyta.com Thu Aug 19 21:18:44 2010 From: ri at fyta.com (=?GB2312?B?x+vXqsXg0bWyv8PF?=) Date: Fri, 20 Aug 2010 05:18:44 +0800 Subject: =?GB2312?B?xvPStc2j16S6y9DEyMuyxQ==?= Message-ID: <201008192118.o7JLIgpq018436@mx1.redhat.com> ???????????--?????? ???????????????? ???????????????? ??????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????2010?8?20-21? ?? ?????2010?8?24-25? ?? ?????2010?9?3-4? ?? ?????2010?9?10-11? ?? ??????????????????????????????????????????HR???????? ? ??4500?/2?/? ???????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ???? ???????????????? ???????????????? ???????????????? ??????????????? ?????????????? ?????????????? ?????????? ????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????? ?????????????????????????????? ???????????????????????????????????? ???????????????????????????? ?? ??,???????????????????????????????????????????????? ????????????,????????????????????????????????? ================================================================================== ???? ?????---???????????,????????????????????????????????? ?????????????? ???????---??????????????????????????? ???????---??????????????????????????????????????????? ??????????????? ???????---??????????????????????????????????????????? ????????????????????????????????????????????????????? ???????---??????????workshop????????????????????????????? ???????????????????? ====================================================================================== ??????? ?????---????????? ???????????????????????????????????????????????????? ????????????????????????????????????????????????????? ???????????????????????????? ??????????????????? ??????????????? ?????????????????????? ???????????????????? ??????????????? ?????????????????????????????? ????????????????????????????????????????95% ?????????????? ??????????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ???????????????????? ?????20?????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????? ?????????????????????????????????????????ESOP????????????????? ???????????????????????????????????????????????????????????? ?????? ??????? ???????????????????????????? ????????????EMAB????????????????4????1? ?????????10???100????????????????????????????????????????????? ?????????????????? ?????????????????????????????????????? ====================================================================================== ????---???? ??? ????????? ???????????? 1????????? 2????????? 3????????? 4????????? 5????????? ???????VS?????????vs????? ????----???????????? 1????? 2???????? 3???????? 4??????? ?????????????????????????? ???????? ????----?????????? 1??"?"???"?"? 2???????????????????? 3???????????????????????????? 4?????? 5?????????????? ?????????????????????????????????? ????----????????? 1???????????????????????? 2????????????? 3?????????????? 4???????????? ??1???????VS ??????? ??2???????????????????????? ????----??????????? 1????????? 2??1%?10% 3?????????? ?????????????????????????????????????????? ?????????? ????----??????? 1? ????vs???? 2? ???????????? 3? ????????? 4? 8???? ???????????????????? ????????????? ??? ?????????? ???????????????? 1??????????????? 2?????7?? ??????????????? 1?TCL???????????? 2????????????? 3?????????? ??????????????? 1? ?????????? 2? ???????? 3? ???????????? 4??????????????? ???????????????? ??? ?????????? 1???????????????? 2??????????????? 3????????????? 4???? ?????????????? 5??????????? ????????????????????? ??? ?????????? 1????????? 2??????????????????? ????????????????????????????????? ??? ??????????? ??????????????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????--????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From roland at redhat.com Thu Aug 19 21:22:29 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 14:22:29 -0700 (PDT) Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: Oleg Nesterov's message of Tuesday, 17 August 2010 16:27:51 +0200 <20100817142751.GA9649@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> Message-ID: <20100819212229.BC4F940080@magilla.sf.frob.com> > > report_reap is covered with the utrace_detached_reap() stub. Every other > > callback uses start_callback(), i.e. calls report_quiesce first. > > utrace_detached_quiesce() returns UTRACE_DETACH, > > Assuming ->report_quiesce() will be called. > > Suppose that, say, engine->flags == UTRACE_EVENT(EXEC) (no QUIESCE). > > 1. start_callback() reads want = engine->flags (== EXEC) > > 2. mark_engine_detached() sets engine->ops = &utrace_detached_ops > > 3. start_callback() gets ops = utrace_detached_ops Right, good point. > OK, instead of filling utrace_detached_ops{} we can change start_callback() > > - if (want & UTRACE_EVENT(QUIESCE)) { > + if ((want & UTRACE_EVENT(QUIESCE)) || ops == detached_ops) { If we're going to have a special-case check for &utrace_detached_ops, then it can just short-circuit entirely and there is no need for any callbacks in utrace_detached_ops. (Then we might even use NULL or (void *)-1l instead of &utrace_detached_ops.) All it needs to do is: report->detaches = true; utrace->reporting = NULL; return NULL; > In particular, I'd like to think if we can simplify this somehow. > Say, avoid the barriers somewhere, or avoid changing engine->flags in > mark_engine_detached(). Yeah. The original idea of changing engine->flags was just to make sure it had QUIESCE so that it would be noticed and detached on any next callback run, not just one that happened to be for the events it was previously tracing (which could be only rare ones, or none but implicit reap). But if we have a special case check in start_callback() before even looking at the flags, then it doesn't matter at all what the flags are. > I am worried that mark_engine_detached() sets engine->flags, but it > doesn't add QUIESCE to utrace_flags. I can't convince myself that > utrace_do_stop() closes all possible races. Ok. The worst case races should not be real problems, only delays in the final engine cleanup. Any eventual utrace_reset() or reaping will of course clean it up at some point. > And, in particular, I don't understand this code in utrace_get_signal: > > } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { > /* > * We only got here to clear utrace->signal_handler. > */ > return -1; > } > > How so? What if we were called because of utrace_control(INTERRUPT) > and QUIESCE is not set? If an engine used UTRACE_INTERRUPT without having first set QUIESCE, then it has no rightful expectation of getting any callback. Thanks, Roland From roland at redhat.com Thu Aug 19 21:44:57 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 14:44:57 -0700 (PDT) Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction In-Reply-To: Oleg Nesterov's message of Wednesday, 18 August 2010 15:48:03 +0200 <20100818134803.GA21031@redhat.com> References: <20100816093929.GA24436@redhat.com> <20100817004443.D95244007E@magilla.sf.frob.com> <20100817173542.GA20692@redhat.com> <20100818134803.GA21031@redhat.com> Message-ID: <20100819214457.E459840080@magilla.sf.frob.com> > Wait. It doesn't break this. It only breaks -EALREADY contract. And > I don't understand why this is bad. The -EALREADY contract lets you have a report_death callback that does all your cleanup and then returns UTRACE_DETACH. To have that plan, you need a way for an asynchronous detach attempt to be excluded once report_death has begun, and for that asynchronous caller to know that's the situation. > > But in any case, personally I dislike the current behaviour anyway, > > I think this certainly complicates the life for module writers. > > Instead of simple detach + barrier, you always need the nontrivial > > code if report_quiesce/death ever touches engine->data! This can't > > be good. > > Yes. > > Roland, could you explain once again why do you dislike this patch? It breaks the documented API. I am of course open to changing the API. But we need to get completely clear on what the new range of plans we'll support is, and make the documentation and the implementation match. > Once again. Currently utrace_control(DETACH) refuses to even try to > detach the engine if utrace->death is set. Correct. > Why? What is the point? What makes UTRACE_EVENT(DEATH) so special? > I do not see the logic at all. It is special because it is the last interesting event to a traditional user such as ptrace. Hence it is attractive to write a report_death callback that returns UTRACE_DETACH "spontaneously", i.e. without an asynchronous caller (i.e. debugger thread) having requested the detach. > If ->report_death() does something which the caller of utrace_control() > should know, then they should take care of synchronization anyway. > With or without this patch, utrace_control(DEATH) can return 0 after > ->report_death() was already called. If your engine's report_death always returns UTRACE_DETACH, then utrace_control(UTRACE_DETACH) can never return 0 once report_death is about to be called nor any time thereafter. > Please correct me, but I think this certainly makes things much simpler. > Otherwise UTRACE_DETACH is never trivial (and iiuc it is better to > avoid utrace_engine_ops->release() hook). > > What do you think? It is a plausible path, treating report_death and all other callbacks alike. As I said, the thinking behind the report_death/report_reap cases came before we had utrace_barrier at all. It's appropriate to rethink the entire set of synchronization schemes in light of practical experience writing some good, clean engines. But, the current state of play from the broader perspective is that we really have no idea about the future viability of the utrace API. I don't think it makes a lot of sense to put a great deal of effort into perfecting the corners of the API much further when we don't really have any good reasons to think that this API will be the basis of anything that survives in the long run. The current focus of work is your ugdb prototype. If some utrace changes make it greatly easier to get that to kind-of-working status, then they are worthwhile. OTOH, if instead you can work around these issues to build something on the existing utrace API, that has the benefit that people can try out your prototype on existing Fedora and RHEL6-beta kernels right away. It is more important right now to make feature progress on the ugdb prototype than to make it robust against uncommon corner cases. If it works in practice but has disturbing robustness holes, it is OK to just comment that loudly now and move on to the next battle, IMHO. For example, I think you should be able to handle an -EALREADY result from utrace_control(UTRACE_DETACH) by calling utrace_barrier and then repeating, possibly in a loop to handle the race where it wasn't your callback running yet. That is terribly clunky, but it lets you get back to working on features rather than utrace guts. Thanks, Roland From mkt at refrimur.com Thu Aug 19 22:04:26 2010 From: mkt at refrimur.com (Refrimur) Date: Thu, 19 Aug 2010 19:04:26 -0300 Subject: Campanha Agosto(II) REFRIMUR 2010 Message-ID:   Problemas para visualizar a mensagem? Clique aqui.   Caso não deseje mais receber esta Newsletter, Clique Aqui       -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Thu Aug 19 22:24:43 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 15:24:43 -0700 (PDT) Subject: [PATCH] fix mark_engine_detached() vs start_callback() race In-Reply-To: Oleg Nesterov's message of Wednesday, 18 August 2010 18:32:33 +0200 <20100818163233.GA31062@redhat.com> References: <20100818163233.GA31062@redhat.com> Message-ID: <20100819222443.7EE9740080@magilla.sf.frob.com> > This is the minimal temporary ugly fix for now, we should certainly > cleanup and simplify this logic. The barriers in mark_engine_detached() > and in start_callback() can't help and should be removed. If we ignore > utrace_get_signal() we do not even need utrace_detached_quiesce(), > start_callback() could just do Agreed. I applied the patch for now. > I think in the longer term mark_engine_detached() should not change > engine->flags at all but add QUIESCE to ->utrace_flags. However, this > breaks utrace_maybe_reap(reap => true) and we should avoid the race > with finish_callback() which clears ->reporting after report_quiesce(). What's the benefit to adding QUIESCE? If any utrace code gets entered at all, then any callback run will be able to do the special-case ops check for detached engines. > A bit off-topic, but I don't think finish_callback() should check > engine->ops == &utrace_detached_ops before return. Instead we should > change finish_callback_report() to return the boolean. We shouldn't > return true without setting report->detaches. Ok. Thanks, Roland From roland at redhat.com Thu Aug 19 23:00:09 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 16:00:09 -0700 (PDT) Subject: [PATCH?] avoid the unnecessary utrace_resume()->utrace_reset() In-Reply-To: Oleg Nesterov's message of Wednesday, 18 August 2010 20:11:47 +0200 <20100818181147.GA4995@redhat.com> References: <20100818181147.GA4995@redhat.com> Message-ID: <20100819230009.886E840080@magilla.sf.frob.com> > utrace_resume(UTRACE_REPORT) always calls utrace_reset() because > start_callback() obviously can't clear report->spurious when > event == 0. > > Change start_callback() to correctly clear ->spurious in this case. Ok. > Note: utrace_control(DETACH) does utrace_do_stop() and sets UTRACE_REPORT > if the tracee is not stopped. It also does mark_engine_detached() which > does not set QUIESCE in target->utrace_flags. This means we rely on > report.spurious which should provoke utrace_reset() from utrace_resume() > if target->utrace_flags doesn't have QUIESCE. A bit too subtle, imho. Agreed. There is no reason utrace_control can't set it in utrace_flags in its !reset case. > Also, UTRACE_REPORT can be lost because of UTRACE_INTERRUPT or normal > signal: utrace_get_signal() checks "utrace_flags & UTRACE_EVENT(QUIESCE)" > and returns otherwise. This should be fixed somehow. This check is wrong > anyway, but it is not clear how we can fix the race with DETACH. I see. That would be fixed by utrace_control setting it. Thanks, Roland From roland at redhat.com Thu Aug 19 23:14:03 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 19 Aug 2010 16:14:03 -0700 (PDT) Subject: gdbstub initial code, v4 In-Reply-To: Oleg Nesterov's message of Thursday, 19 August 2010 19:49:55 +0200 <20100819174955.GA14618@redhat.com> References: <20100819174955.GA14618@redhat.com> Message-ID: <20100819231403.C323940080@magilla.sf.frob.com> > Note the second attachment, GDBCAT. It is just the simple perl > script which connects /proc/ugdb to tcp port. It can be used for > remote debugging via tcp, or with (unpatched) gdb which can't do > select() on /proc/ugdb. bash$ nc -l 2000 <> /proc/ugdb & > Actually, it is more convenient to use > it in any case, at least for logging purposes. (gdb) set remote debug 1 Thanks, Roland From ertw43342 at srew.com Fri Aug 20 16:03:49 2010 From: ertw43342 at srew.com (ertw43342 at srew.com) Date: Sat, 21 Aug 2010 00:03:49 +0800 Subject: =?GB2312?B?vfiz9r/ataXWpDkxNTQ4NQ==?= Message-ID: <201008201603.o7KG3pME006332@mx1.redhat.com> ????????? ???????????/????/???????? ???(CO/FA/FE/FF) ????,????????????, ??? ? ????? ?????, ???????????? ??/ ??????!??????????????????????????!! ??????????(??)?????????????????????? ?????????????????? ??????????????????????????????? ?????13713821291??QQ317784868 From oleg at redhat.com Fri Aug 20 17:37:49 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Aug 2010 19:37:49 +0200 Subject: gdbstub initial code, v5 Message-ID: <20100820173749.GA24358@redhat.com> On 08/19, Oleg Nesterov wrote: > > Next step: handle exit correctly and report W/S. I misunderstood > what gdbserver does when the main thread exits, it is not stupid > as I wrongly thought. Yes, in non-stop mode gdbserver reports W/X;process:PID when the last thread exits. This makes sense, so does ugdb. But, ================================================================== All, please ack/nack the behavioral difference! When the main thread exits, gdbserver still exposes it to gdb as a running process. It is visible via "info threads", you can switch to this thread, $Tp or $Hx result in "OK" as if this thread is alive. gdbserver even pretends that $vCont;x:DEAD_THEAD works, although this thread obviously can never report something. I don't think this is really right. This just confuses the user, and imho this should be considered like the minor bug. ugdb doesn't do this. If the main thread exits - it exits like any other thread. I played with gdb, it seems to handle this case fine. ================================================================== Problems: - I forgot to implement the attach to the thread group with the dead leader. Next time. - The exit code (Wxx) can be wrong in mt-case. The problem is, ->report_death can't safely access ->group_exit_code with kernel < 2.6.35. This is solveable. Roland, sorry, I ignored your emails for today. It is not easy to me to switch between ugdb an utrace ;) Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { // XXX: temporary racy check WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_code; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { struct task_struct *task; BUG_ON(!thread_alive(thread)); task = pid_task(thread->t_spid, PIDTYPE_PID); BUG_ON(!task); return task; } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static inline void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (list_empty(&thread->t_stopped)) return; WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH)); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* * Ensure a callback can't race with utrace_destroy_thread(). * If we race with ugdb_report_clone() or ugdb_report_death(), * they must see P_DETACHING under ->u_mutex. */ if (ret == -EINPROGRESS) utrace_barrier_pid(thread->t_spid, thread->t_engine); } static const struct utrace_engine_ops ugdb_utrace_ops; /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct ugdb_thread *ugdb_attach_main(struct ugdb *ugdb, struct ugdb_process *process) { struct ugdb_thread *thread; struct pid *spid; spid = find_get_pid(process->p_pid); if (!spid) return NULL; thread = ugdb_attach_thread(process, spid); if (IS_ERR(thread)) thread = NULL; put_pid(spid); return thread; } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct pid *next = NULL; task = pid_task(curr, PIDTYPE_PID); BUG_ON(!task); spin_lock_irq(&task->sighand->siglock); for (;;) { task = next_thread(task); // XXX: BUG: if main is not group leader we can race with exec if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&task->sighand->siglock); return next; } static int ugdb_attach(struct ugdb *ugdb, int pid) { struct ugdb_process *process; struct ugdb_thread *thread; struct pid *main_pid, *curr_pid; // XXX: check if exists process = ugdb_create_process(ugdb, pid); if (!process) goto err; mutex_lock(&ugdb->u_mutex); // XXX: check if group leader ? thread = ugdb_attach_main(ugdb, process); if (!thread) goto abort; main_pid = thread->t_spid; curr_pid = main_pid; for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } // XXX mark it just attached mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); ugdb_destroy_process(process); err: return -1; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); WARN_ON(thread->t_stop_state & T_STOP_ACK); if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; ret = true; thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! thread->t_stop_code = current->exit_code; // XXX: temporary, for ugdb_add_stopped() thread->t_stop_state = T_STOP_REQ; ugdb_add_stopped(thread); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { /* * (gdb) interrupt & * (gbd) interrupt -a & * * make sure -a actually works if it races with clone. */ if (all && !(thread->t_stop_state & T_STOP_ALL)) { /* * We hold ugdb->u_mutex, so we can't race with * ugdb_report_clone(). But we need spinlock to * avoid the race with ugdb_add_stopped() which * can change ->t_stop_state in parallel. */ spin_lock(&ugdb->u_slock); thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); } return 0; } // XXX: currently we can do this lockless ... thread->t_stop_state = all ? (T_STOP_REQ | T_STOP_ALL) : T_STOP_REQ; thread->t_stop_code = 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!process_alive(thread->t_process)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!process_alive(process)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!process_alive(process)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, live, code; struct pbuf *pb; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; live = thread_alive(thread); code = thread->t_stop_code; pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } // X9;process:4aee // W0;process:4f1c if (live) { pb_printf(pb, "%sthread:p%x.%x;", "T00", pid, tid); } else { char r; if (code & 0xff) { // XXX: renumber signal! code &= 0xff; r = 'X'; } else { code >>= 8; r = 'W'; } pb_printf(pb, "%c%x;process:%x", r, code, pid); ugdb_destroy_process(thread->t_process); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } count = pb_copy_to_user(pb, ubuf, count); if (count > 0) *ppos += count; return count; } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); *ppos += count; return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Fri Aug 20 17:49:28 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Aug 2010 19:49:28 +0200 Subject: gdbstub initial code, v4 In-Reply-To: <20100819231403.C323940080@magilla.sf.frob.com> References: <20100819174955.GA14618@redhat.com> <20100819231403.C323940080@magilla.sf.frob.com> Message-ID: <20100820174928.GA25352@redhat.com> On 08/19, Roland McGrath wrote: > > > Note the second attachment, GDBCAT. It is just the simple perl > > script which connects /proc/ugdb to tcp port. It can be used for > > remote debugging via tcp, or with (unpatched) gdb which can't do > > select() on /proc/ugdb. > > bash$ nc -l 2000 <> /proc/ugdb & Yes, this works, > > Actually, it is more convenient to use > > it in any case, at least for logging purposes. > > (gdb) set remote debug 1 set debug remote 1. Yes, I tried this. Very, very inconvenient. In this case the debugging output is mixed with the normal output, Also: you can't save to file, can't filter packets, can't add the packet for debugging (not implemented yet). But yes, it is not strictly necessary, nc should work too. Oleg. From dan at codesourcery.com Fri Aug 20 18:21:22 2010 From: dan at codesourcery.com (Daniel Jacobowitz) Date: Fri, 20 Aug 2010 14:21:22 -0400 Subject: gdbstub initial code, v4 In-Reply-To: <20100820174928.GA25352@redhat.com> References: <20100819174955.GA14618@redhat.com> <20100819231403.C323940080@magilla.sf.frob.com> <20100820174928.GA25352@redhat.com> Message-ID: <20100820182120.GA8316@caradoc.them.org> On Fri, Aug 20, 2010 at 07:49:28PM +0200, Oleg Nesterov wrote: > > (gdb) set remote debug 1 > > set debug remote 1. Yes, I tried this. Very, very inconvenient. > In this case the debugging output is mixed with the normal output, > > Also: you can't save to file, can't filter packets, can't add > the packet for debugging (not implemented yet). set remotelogfile filename addresses those first two. I don't know what you mean by the last thing, but if it's useful, gdb can perhaps grow a way to do it. -- Daniel Jacobowitz CodeSourcery From delimited at frostway.com Sat Aug 21 04:52:30 2010 From: delimited at frostway.com (Juvera Wiltshire) Date: Sat, 21 Aug 2010 06:52:30 +0200 Subject: Your wife photos attached Message-ID: <4C6F590C.1050907@frostway.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: veratrum.zip Type: application/octet-stream Size: 12188 bytes Desc: not available URL: From lomantodl at hotmail.com Sat Aug 21 07:19:35 2010 From: lomantodl at hotmail.com (Don Lomanto) Date: Sat, 21 Aug 2010 03:19:35 -0400 Subject: =?gb2312?B?sdjQ69ei0uK1xNK7uPbSqrXjo7o=?= =?gb2312?Q?26o?= Message-ID: ?????????????? ?????????????????? ?????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????\??????? ?????????????????????? ?????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? ???????????????~?????????????????????????????? ??????????????????????????????10?????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????? 1. ????????????????????????????????????????=?????????????? ????28000?? 2. ??????????????????????????????????CEO?????????????? ????15800?? 3. ??????????????????????????????????????????????DVD ????29800?? 4. ???????????????????????????????????????????????????????? ????2980?? 5. ????????????????????????????.???????????????????????????????????? 6. ????????????????????????????.????08??09?????????????? ????38000?? 7. ?????????????????????????? ???????????????????? ???????????? 8. ???????????????????????????????????????????????? 9. ???????????????????????????????????????????? ????22000?? 10.?????????????????????????????????? ??????DVD ????22000?? PS?????????????? ?????????????? ???????????????????????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From silverizes at touch-stone.com Sun Aug 22 19:16:20 2010 From: silverizes at touch-stone.com (Askew Ellsmore) Date: Sun, 22 Aug 2010 16:16:20 -0300 Subject: Your wife photos attached Message-ID: <4C7176F1.7010305@touch-stone.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: reasonable.zip Type: application/octet-stream Size: 12337 bytes Desc: not available URL: From zhengjie201007 at gmail.com Mon Aug 23 02:03:52 2010 From: zhengjie201007 at gmail.com (jie zheng) Date: Mon, 23 Aug 2010 10:03:52 +0800 Subject: =?GB2312?B?ufq80reiuMTOryA5LjEwINeoz+7Xyr3wyeqxqDE1?= Message-ID: ????? 9.10 ??????1501 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ????? 9.10 ??????.doc Type: application/msword Size: 154112 bytes Desc: not available URL: From kit at masteremarketing.com.br Mon Aug 23 04:42:51 2010 From: kit at masteremarketing.com.br (Kitmaladireta) Date: Mon, 23 Aug 2010 01:42:51 -0300 Subject: =?UTF-8?B?U3VwZXJraXQyMDEwIC0gbWFuZGUgMSBtaWxow6NvIGRlIGVtYWlscw==?= Message-ID: <0620db3529a9afd0a009542dbf4c574a@187.33.3.203> An HTML attachment was scrubbed... URL: From joy.abubakar at yahoo.com Mon Aug 23 11:04:51 2010 From: joy.abubakar at yahoo.com (Vera R. Awaza) Date: Mon, 23 Aug 2010 04:04:51 -0700 (PDT) Subject: Hello My Dear, Message-ID: <423542.88578.qm@web110801.mail.gq1.yahoo.com> Hello My Dear, How are you today i hope you are fine. My name is Miss Vera R.Awaza. My dear, i will like you to be my friend. I came on (NET) to? look for a friend of my own that is read to build up a good relationship that will last for the test of time, if you are interested in hooking up pleass write me email at(Vera_babylive884u at yahoo.com) i will tell you more about me and also send you my photo in my next mail ok -------------- next part -------------- An HTML attachment was scrubbed... URL: From xzw at ghmt.com Mon Aug 23 16:23:21 2010 From: xzw at ghmt.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Tue, 24 Aug 2010 00:23:21 +0800 Subject: =?GB2312?B?VDF1dHJhY2UtZGV2ZWy3x7LGzvG437nctcSyxs7x0+vLsM7xudzA7Q==?= Message-ID: <201008231623.o7NGNLEs014686@mx1.redhat.com> utrace-devel?????????????????????????? ??????????2010??8??27-28?? ???? ??????????2010??9??03-04?? ???? ??????????2010??9??17-18?? ???? ?????????????????????????????????????????????????????????????????????? ??????????2980??/??(????????????????????????????????????????) ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? ----------------------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????? 1?????????????????????????????????????????????????????????????????????????? 2???????????????????????????????????????????????????????????? 3?????????????????????????????????? 4???????????????????????????????????????????????????????????????????? 5???????????????????????????????????????????????????????? 6?????????????????????????????????????????????????????????? 7?????????????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????? 9?????????????????????????????????????????????????????????????????? 10?????????????????????????????????????????????????????????????????????? 11???????????????????????????????????????????????????????????????? 12?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????? ?????????????????? ???????????????????????????????????????????????? 1?????????????????????????????????????????????? 2???????????????????????????????? 3?????????????????????????? 4?????????????????????? 5???????????????????????? 6???????????????????????????????????? 7???????????????????????????????? 8?????????????????????????? ?????????????????????????????????? ???????????????????????????????????????????????????? ?????????????????????????? 1?????????????????????????????????????????????????????? 2???????????????????????????? 3?????????????????????????????????????????????????????????????????? ???????????????????????????????? 1?????????????????????? 2?????????????????????? 3???????????????????????????????? 4?????????????????????? 5?????????????????????????????????????????????????????????? 6???????????????????????????????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2???????????????????? ???????????????????????????? 1?????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3???????????????????????????????????????????????????? ?????????????????????????? 1???????????????????????????? 2???????????????????????????????????????????? 3?????????????????????????????????? 4.???????????????????? ???????????????? ?????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????????? 1?????????????????????? 2???????????????????????????? 3???????????????????????? 4???????????????????????????????????????????? 5?????????????????????????????????????????????????? 6???????????????????????????????????????? 7?????????????????????????????????????????????????????????? 8?????????????????????????????? 9?????????????????????????? 10???????????????????????? ???????????????????????????? 1?????????????????? 2?????????????????????????? 3?????????????????????????????????????????????????????? 4???????????????????????????? 5?????????????????????????? 6???????????? ?????????????????? 1?????????????????????????????????????????? 2?????????????????????????????????????????????????? ??????????????KPI??????????SMART???? ?????????????????? ?????????????????????????????????????????? 1?????????????????????? ???????????????????????????????????????????????????????????? ???????????? 2???????????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????? 1?????????????????????????????????????????????????????????????????????????????? 2???????????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????????????? 4?????????????????????????????????????????????????? 5???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????? 6???????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????????????????????????????? 1?????????????????????????????????????????????????????????????????? 2???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????????????????????????? ???????????????? 4?????????????????????????????????????????????????????????????? 5???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????? 6???????????????????????????????????????????????????????????????????????? ?????????? 7???????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????????????????? ?????????????????????????? 1???????????????????????????????????????????????????????????? 2?????????????????????????????????????????????????????????????????????????? ?????????????????????????? ?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????? 1???????????????????????????????????????? 2?????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? ?????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? --------------------------------------- ????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From oleg at redhat.com Mon Aug 23 18:52:23 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 23 Aug 2010 20:52:23 +0200 Subject: gdbstub initial code, v5 In-Reply-To: <20100820173749.GA24358@redhat.com> References: <20100820173749.GA24358@redhat.com> Message-ID: <20100823185223.GA31912@redhat.com> Just a small report to explain what I am doing... On 08/20, Oleg Nesterov wrote: > > - I forgot to implement the attach to the thread group > with the dead leader. Next time. Almost done, but we should avoid the races with exec somehow. But this is minor. I tried to test this code as much as I can. Again, I do not use gdb at all, I am using the scripts which try to really stress ugdb. Found 2 bugs in ugdb.ko, the second one is not nice but at least I have the temporary fix. However. I spent all Monday trying to resolve the new bug, and so far I do not understand what happens. Extremely hard to reproduce, and the kernel just hangs silently, without any message. So far I suspect the proble in utrace.c, but this time I am not sure. Will continue tomorrow... Oleg. From reprobates at peoples.sk Tue Aug 24 10:59:18 2010 From: reprobates at peoples.sk (Montuoro Ditch) Date: Tue, 24 Aug 2010 12:59:18 +0200 Subject: Your wife photos attached Message-ID: <4C73A56B.9090308@peoples.sk> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: dipeptide.zip Type: application/octet-stream Size: 12575 bytes Desc: not available URL: From oleg at redhat.com Tue Aug 24 17:07:18 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Aug 2010 19:07:18 +0200 Subject: gdbstub initial code, v5 In-Reply-To: <20100823185223.GA31912@redhat.com> References: <20100820173749.GA24358@redhat.com> <20100823185223.GA31912@redhat.com> Message-ID: <20100824170718.GA8966@redhat.com> On 08/23, Oleg Nesterov wrote: > > However. I spent all Monday trying to resolve the new bug, and > so far I do not understand what happens. Extremely hard to reproduce, > and the kernel just hangs silently, without any message. > So far I suspect the proble in utrace.c, but this time I am not sure. Solved. This was scheduler bug fixed in 2.6.35, but I used 2.6.34. This is really funny. This bug (PF_STARTING lockup) was found and fixed by me & Peter. Oh. But I hit yet another problem, BUG_ON() in __utrace_engine_release(). Again, it is not reproducible, I saw it only once in dmesg and I do not even know for sure what I was doing. I'll contiue tomorrow, but if I won't be able to quickly resolve this problem I am going to ignore it for now. This time I think ugdb is wrong. Oleg. From roland at redhat.com Tue Aug 24 23:36:00 2010 From: roland at redhat.com (Roland McGrath) Date: Tue, 24 Aug 2010 16:36:00 -0700 (PDT) Subject: gdbstub initial code, v5 In-Reply-To: Oleg Nesterov's message of Friday, 20 August 2010 19:37:49 +0200 <20100820173749.GA24358@redhat.com> References: <20100820173749.GA24358@redhat.com> Message-ID: <20100824233600.4A3184048C@magilla.sf.frob.com> > When the main thread exits, gdbserver still exposes it to gdb as > a running process. It is visible via "info threads", you can switch > to this thread, $Tp or $Hx result in "OK" as if this thread is alive. > gdbserver even pretends that $vCont;x:DEAD_THEAD works, although > this thread obviously can never report something. This is sort of consistent with the kernel treatment. The main thread stays around as a zombie, acting as a moniker for the whole process. But indeed that is not actually useful for any thread-granularity control or information (well, there is the dead thread's usage stats, but that's all). > I don't think this is really right. This just confuses the user, and > imho this should be considered like the minor bug. I tend to agree, but don't think it's a big issue either way, really. > ugdb doesn't do this. If the main thread exits - it exits like any > other thread. I played with gdb, it seems to handle this case fine. Sounds good to me! > - The exit code (Wxx) can be wrong in mt-case. > > The problem is, ->report_death can't safely access > ->group_exit_code with kernel < 2.6.35. This is > solveable. Don't even worry about it. If there is something trivial to do that makes it better for earlier kernels, then go ahead. But if the easy thing to do gives correct results on >=2.6.35 and racily wrong or random results on older kernels, then we can just live with that. Thanks, Roland From idiotises at acscad.co.th Wed Aug 25 21:46:11 2010 From: idiotises at acscad.co.th (Nolden Belleville) Date: Wed, 25 Aug 2010 23:46:11 +0200 Subject: Your wife photos attached Message-ID: <4C758E83.2080301@acscad.co.th> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: footslog.zip Type: application/octet-stream Size: 11117 bytes Desc: not available URL: From bnk at wevj.com Thu Aug 26 09:53:28 2010 From: bnk at wevj.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 26 Aug 2010 17:53:28 +0800 Subject: =?GB2312?B?Qzd1dHJhY2UtZGV2ZWzP+srb1ve53LykwPg=?= Message-ID: <201008260953.o7Q9rPe1030617@mx1.redhat.com> utrace-devel????2?1??? ?????2010?8?28-29? ?? ?????2010?09?04-05? ?? ?????2010?09?11-12? ?? ?????????????????????????????? ?????2880?(2??,1?? ??,?????,???,???) ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ???? 1.?????????????????????????????? 2.???????????????????????????? 3.???????????????????????????????? 4.??????????????????????????? 5.?????????????????????????? 6.??????????????????????????? 7.??????????????????????? 8.?????????????????????????????? 9.????????????????????????????? 10??????????????????????????????????? 11. ??????????????????????????? 12. ?????????????????????????????? ?????????????????????????????????????? ???? 1.2?????61?????????? 2.?????????????????????? 3.????????????????? 4.???????????? ????????????????????? ??????????????????? ????????????????????????? ?????????????????????????????????????? ???? ????????????????????????????????????? ????????????????????????????? ?????????????????????????????????????? ?????? ?? 1.????????????????? 2.??????????????? 3.??????????????????? 4.?????????????????? 5.?????????????????????? ????? ?????----- ??????????????? ?????????????????? 1????????? ??????? 2???????? ? ??? 3???????????????? ? ???? 4??????????? ??? ???? 5???????? ????? ???? 6????????????? ? ???? 7????????????? ?????? 8?????????? ???? ???? 9??????????????? ? ???? ????? ????-----??????????????? ?????????? 1.??????????????????? 2.??????????????????? 3????????????? 4????????????????????? 5????????????????? 6???????????????? 7??????????6???? ???????? ?? ????????????????? ? ??????????????????? ? ?????????????????? ? ????????????? 1?????????????????? 2???????????????????? 3??????????????? 4??????????????? 5????????????? 6??????????????????? ??????????????????????? ?????????????????? ???????? ??? 1.???????????????????????? 2.????????????????????? 3.????????????????? 4.???????????????? 5.??????????????????? 6.??????????????????????????? ???????????????? ????????????? 1.??????????????? 2.????????????? 3.??????5???? ?????????????????? 1.??????????????????????? 2.????????????3???? 3.???????3???? ???9??? 4.??????6??? ???????????? ????????6???? ????????????? ?? ???????????????? 1.??????????? 2.??????????5??? 3.?????????7???? 4.??????????6???? 5.????????8??? 6.????????7??? 7.????5????? ??? ???????10???? ???? ??????? 1.???????????????? 2.??????????????????? ???????????????????????? ???????????3??? 3.??????????????? ???????????????? ??????????????????? ????????5??? ??????????????????? ??????????? 4.?????????7????? ???? ???? 1.?????????????????? 2.???????????????????? 3.???????????????????? 4.???????????????? 5.??????????????? 6.????????????????? ???? ???????? 1.??????????????????? 2.????????????????? 3.???????????????? 4.???????????????? 5.????????????????? 6.?????????????????? ??????????4??? ?????????????????????????????????????? ????????? ????????????? ???????????????? ????????????????? ???????????????????? ????.????.????EMBA?????? 2000?????????????????????,???????????????? ?????????????,?????????100??????????????? ????????????,?????????,????????????????? ?????????????????????????????? ????? ??????????? ?????????? ???????????? ???????? ????????? ???????????? ??????? ??????????? ????/??????/????/????/????/????/???/??/????/ ??????/????/??????/????/??????/??????/???? ??/?????/??????/?????/???????/?????/??????/ ??????/????/????/????/????/???????/????/??? ?/???????????/??????? --------------------------------------- ?????2?1???????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Thu Aug 26 16:57:28 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Aug 2010 18:57:28 +0200 Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case In-Reply-To: <20100819211131.9862E40080@magilla.sf.frob.com> References: <20100814023128.GA9236@redhat.com> <20100817001308.D335D4007E@magilla.sf.frob.com> <20100817115534.GA30214@redhat.com> <20100819211131.9862E40080@magilla.sf.frob.com> Message-ID: <20100826165728.GA20425@redhat.com> On 08/19, Roland McGrath wrote: > > > On 08/16, Roland McGrath wrote: > > > > > Now that you merged c93fecc925ea7567168f0c94414b9021de2708c5 > > "get_utrace_lock() must not succeed if utrace->reap == T", this becomes > > a bit off-topic. However, I thought about relaxing the "dead" check in > > get_utrace_lock(), instead of utrace->reap we could check > > "utrace->reap && !utrace->death". In fact, initially I was going to > > do this, but then decided to make the simpler patch for now. > > When utrace->reap is set, it means release_task() has been called. The > API caller has no way to know reaping hasn't already begun--except if > its report_death callback has not returned yet. No! the task can be already reaped even before ->report_death() was called. The task_struct itself can't go away, but that is all (perhaps you meant this). And this is the problem for ugdb. Damn, I knew this, that is why ugdb_process_exit() doesn't try to read ->group_exit_code. Still I managed to forget that this has other implications. > But I think that the > API definition of "once release_task() has been called (i.e. entered, > maybe not returned yet), any utrace call will get -ESRCH", is a clear > and comprehensible constraint. We should not open any holes in that. I am not sure. I had another reason in mind to check reap && !death in get_utrace_lock(), synchronization with ->report_death() callback. But OK. Let's forget about more utrace changes for now. Oleg. From oleg at redhat.com Thu Aug 26 17:13:55 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Aug 2010 19:13:55 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100819212229.BC4F940080@magilla.sf.frob.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> Message-ID: <20100826171355.GB20425@redhat.com> On 08/19, Roland McGrath wrote: > > > OK, instead of filling utrace_detached_ops{} we can change start_callback() > > > > - if (want & UTRACE_EVENT(QUIESCE)) { > > + if ((want & UTRACE_EVENT(QUIESCE)) || ops == detached_ops) { > > If we're going to have a special-case check for &utrace_detached_ops, then > it can just short-circuit entirely and there is no need for any callbacks > in utrace_detached_ops. (Then we might even use NULL or (void *)-1l > instead of &utrace_detached_ops.) All it needs to do is: > > report->detaches = true; > utrace->reporting = NULL; > return NULL; Yes, I thought about this too, see the changelog. But probably we need utrace_detached_ops->report_reap() anyway. ->report_death can return UTRACE_DETACH, and after that utrace_report_death() can skip utrace_reset() and do ->report_reap(). > > And, in particular, I don't understand this code in utrace_get_signal: > > > > } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { > > /* > > * We only got here to clear utrace->signal_handler. > > */ > > return -1; > > } > > > > How so? What if we were called because of utrace_control(INTERRUPT) > > and QUIESCE is not set? > > If an engine used UTRACE_INTERRUPT without having first set QUIESCE, > then it has no rightful expectation of getting any callback. Hmm. This is certainly new to me. Could you confirm? If yes, shouldn't we change utrace_control() - if (action >= UTRACE_REPORT && action < UTRACE_RESUME && + if (action >= UTRACE_INTERRUPT && action < UTRACE_RESUME && unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) { then? I must admit, I do not understand why INTERRUPT needs QUIESCE. utrace_get_signal() should respect QUIESCE, this is clear. But why it is needed? Oleg. From oleg at redhat.com Thu Aug 26 17:38:39 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Aug 2010 19:38:39 +0200 Subject: [PATCH 2/3] fix utrace_control(DETACH) && utrace->death interaction In-Reply-To: <20100819214457.E459840080@magilla.sf.frob.com> References: <20100816093929.GA24436@redhat.com> <20100817004443.D95244007E@magilla.sf.frob.com> <20100817173542.GA20692@redhat.com> <20100818134803.GA21031@redhat.com> <20100819214457.E459840080@magilla.sf.frob.com> Message-ID: <20100826173839.GC20425@redhat.com> On 08/19, Roland McGrath wrote: > > > Wait. It doesn't break this. It only breaks -EALREADY contract. And > > I don't understand why this is bad. > > The -EALREADY contract lets you have a report_death callback that does all > your cleanup and then returns UTRACE_DETACH. I think this is possible without the current -EALREADY contract. > To have that plan, you need a > way for an asynchronous detach attempt to be excluded once report_death has > begun, and for that asynchronous caller to know that's the situation. The problem is, with the current conract detach is never simple if you have report_death. You always have to synchronize with this callback. But see below. > It breaks the documented API. I am of course open to changing the API. > But we need to get completely clear on what the new range of plans we'll > support is, and make the documentation and the implementation match. Yes. I thought it makes sense to change the API and docs if we can improve things, before utrace is widely used. But OK, lets's forget about this. > > Why? What is the point? What makes UTRACE_EVENT(DEATH) so special? > > I do not see the logic at all. > > It is special because it is the last interesting event to a traditional > user such as ptrace. Hence it is attractive to write a report_death > callback that returns UTRACE_DETACH "spontaneously", i.e. without an > asynchronous caller (i.e. debugger thread) having requested the detach. Sure. And this is still possible. > > If ->report_death() does something which the caller of utrace_control() > > should know, then they should take care of synchronization anyway. > > With or without this patch, utrace_control(DEATH) can return 0 after > > ->report_death() was already called. > > If your engine's report_death always returns UTRACE_DETACH, then > utrace_control(UTRACE_DETACH) can never return 0 once report_death > is about to be called nor any time thereafter. I don't undestand this. OK, probably I missed something, this doesn't matter. > But, the current state of play from the broader perspective is that we > really have no idea about the future viability of the utrace API. I don't > think it makes a lot of sense to put a great deal of effort into perfecting > the corners of the API much further when we don't really have any good > reasons to think that this API will be the basis of anything that survives > in the long run. Yes. I have to agree, this is good point. So, lets forget about these changes, at least for now. > The current focus of work is your ugdb prototype. If some utrace changes > make it greatly easier to get that to kind-of-working status, then they are > worthwhile. No. I didn't think about ugdb at all. I'll find the workaround for ugdb. If nothing else, I can use utrace_engine_ops->release(). Or something else. > If it > works in practice but has disturbing robustness holes, it is OK to just > comment that loudly now and move on to the next battle, IMHO. OK, agreed. Oleg. From oleg at redhat.com Thu Aug 26 17:51:23 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Aug 2010 19:51:23 +0200 Subject: [PATCH] fix mark_engine_detached() vs start_callback() race In-Reply-To: <20100819222443.7EE9740080@magilla.sf.frob.com> References: <20100818163233.GA31062@redhat.com> <20100819222443.7EE9740080@magilla.sf.frob.com> Message-ID: <20100826175123.GD20425@redhat.com> On 08/19, Roland McGrath wrote: > > > I think in the longer term mark_engine_detached() should not change > > engine->flags at all but add QUIESCE to ->utrace_flags. However, this > > breaks utrace_maybe_reap(reap => true) and we should avoid the race > > with finish_callback() which clears ->reporting after report_quiesce(). > > What's the benefit to adding QUIESCE? If any utrace code gets entered at > all, then any callback run will be able to do the special-case ops check > for detached engines. Well yes, but otoh it could be the last engine. We shouldn't miss, say, start_callback() from utrace_resume() (although currently ->spurious helps). Anyway, this needs more thinking, and probably you are right and QUIESCE is not needed. Oleg. From noreply at no-answer.com Thu Aug 26 22:23:12 2010 From: noreply at no-answer.com (noreply at no-answer.com) Date: Thu, 26 Aug 2010 18:23:12 -0400 Subject: Paralegal Driving Exchange Service Message-ID: <34321933230161958024659@CL-T062-371CN> An HTML attachment was scrubbed... URL: From 88888 at chsi.com.cn Fri Aug 27 03:19:24 2010 From: 88888 at chsi.com.cn (=?GB2312?B?uN/Qvbmk1/fTxbrx1rDOu7unv9rWsLPGx+HLyciruOO2qKOh?=) Date: Fri, 27 Aug 2010 11:19:24 +0800 Subject: =?GB2312?B?w+K2wcfhy8m/7MvZu/HV/bnmzsTGvg==?= Message-ID: <201008270319.o7R3JQs5025003@mx1.redhat.com> ?????????? ?? ?? ?????????????? ???? ???? ???? ???? ???? ???? ????????????????? ????????????????????????????????????????????????????????,????????????????? ??????????????????????????????????????????????????????????????????????????? ???????????????????????????????????!? ?????????????????? ???????????????????????????????,????,????????????????? ?????????????? ??????????????????????????????????,???????????????????????!! ??????: ??????: ?????(??,??)????????,????(??,??)????,????(???,???)?????????(??,???),??????? ????,???,???,?????????? !! ???????,?????????????,??????????,??????,??,??,??,??????, ????? www.chsi.com.cn ?????????? ???????????????: www.chsi.com.cn/xlcx/index.jsp ??????????????????13261188788 ??? ? ????????????????????????????,????????,?????!! ????? 1. ??????? ????????, ???????????, ??? ?? ??? ?? ?? ?? ?? ?? ? 2.????????? ????? ????? ????? ?3500?-10000??? 3.??????? 3-5????? ????? 1.???????: ?????????????, ?????????????????? 2.??????????????????? ?? ?? ?? ?????) , ??(?? ?? ?????), ????(????)??, ????, ???? 3.????????????????20????????????? ????: ?????????????????20%????????????????????????????? ????? www.chsi.com.cn ?????????? ???010-82336088 ???????????????: www.chsi.com.cn/xlcx/index.jsp ?????????????????? 13261188788 ??? ? ????????, ??????,????????????????!! ???????????????????????????????????? ?????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????? ????????? ?? ???????????????????????????????????? ??????????????? ?????????????30????????????? ???? ?????????????????????1205? ????? www.chsi.com.cn ?????????? ???????????????: www.chsi.com.cn/xlcx/index.jsp ?????????????????? 13261188788 ??? From vb at ykjr.com Fri Aug 27 10:57:34 2010 From: vb at ykjr.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Fri, 27 Aug 2010 18:57:34 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyKvE3NDNs7W85Nb3yM7KtdW9vLzE3A==?= Message-ID: <201008271057.o7RAuu7a002751@mx1.redhat.com> utrace-devel??????????? ?????2010?9?10-11? ?? ?????2010?9?17-18? ?? ? ??2200?/? ????????????????? ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ??????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????. ??????????????????????????????????????????????? ??????????????????????????????????????????????! ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? -------------------------------------------------------------------------------------------- ???????????? l?????????????????????????????????????????? 2??????????????????????????????? 3?????????????????????????????????????????? 4????????????????????????????????????????????? 5???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? -------------------------------------------------------------------------------------------- ????? l??????????????????????????????? 2??????????????????? 3????????????????????? 4???????????????????????????? 5??????????????TPM???????? ????? l????????????????????????? 2???????????????????????????????????? 3???????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????? ??????????????? ??????????? ????????????????? ????????????? ?????/?????/????? ?????????????? ??????????? ????????????? ????????????? ???????????????? ????????????????? ???????????????? ???????????????? ???????????? ???????????? ??????????????? ???????????? ??????????? ?????????????? ???????????????? ??????????????? ???????(?????) ?????????????? ????????? ??????????? ????????? ??????????? ????????????? ??:??????????? ???? ??N?????/??????? ???ISO9000??????????? ??????????????? ????????????????TPS? ???????????TOYOTA??? ????????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ????TQM?6?????????? ????????????????????????? ??????????????????? ??????????????? ???TPM??????????????????? ???TPM????????? ???: ???? ???? ??????????? ??????????? ?????????? ????????? ????????? ??: ??????????? ?????????????? ??????? ?????????????????? ??????????? ??????????????? ---???????????,??????????????) ---????????? ---????????? ---???????????? ??????/????????????; ???? 1.??????????????? 2.?????????? ?????????????????; ---???????????? ------------------------------------------------------------------------------------------------------------- ?????????? ?????? ???????? ???????????????(SUMIDA)????????(CASIO) ???13??????????????????????????????????????????????? ??WF&IE ???????????????????????????????????????????????????????JIT ??????NPS????????????? ??????????????(??,??,??,??,?????)????? ?:??????????ST?????????????????????????????????????????????? ???????????????????????????????80?????? ?????????????????????????????????????????????ABB?????????? ?????-??????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ?????????????????????????????? ??????????????????,?????????????????????????????????????? ?????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From vbej at pum.com Fri Aug 27 15:35:53 2010 From: vbej at pum.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Fri, 27 Aug 2010 23:35:53 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyqTIzsGmxKPQzbm5vajT67LixsA=?= Message-ID: <201008271535.o7RFZqO3018180@mx1.redhat.com> utrace-devel?????????? ?????2010?9?3-4? ?? ?????2010?9?17-18? ?? ???3800?/??????????????????? ???????????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ???????????????????????????????????????????????? ???.????????????????????????.???????????????????? ?????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????? ------------------------------------------------------------------------------------------------ ???? ? ?????????????????? ? ???????????? ? ??????????????? ? ??????????????????BEI??? ? ??????????????????? ? ????????????????? ? ???????????????????? ? ?????????????? -------------------------------------------------------------------------------------------------- ???? ???? ???????????? ? ?????? ? ???????????? ? ???????????????????? ? ????????????? ? ???????????? ? ?????GE??????? ? ???????????????????? ? ????????? ? ?????????? ? ?????????? ? ??????????????????????? ? ??????????????? ? ??????? ? ?????????????????????????? ? ??????????????????????? ? ????????????? ? ???????????? ? ????????????????????? ? ????????????????????? ? ????????????????????? ? ?????????? ? ????????????????????? ? ??????????????????? ? ?????????????????? ? ??????????????????????????????? ? ???????? ? ????????????????????? ? ??????????????????? ? ????????????????BEI??? ? ????????????? ? BEI????????? ? BEI???????????? ? BEI????????STAR???? ? STAR???????? ? BEI???? ? ????????? ? ?????????????????????BEI?? ? ????????BEI???????? ? ?????????? ? ?????????????? ? ????? ? ?????????????????????? ? ????????? ? ???????????? ? ?????????????????????? ? ?????????????????? ???? ??????? ? ???????? ? ???????? ? ?????????? ? ???????????????????????? ? ??? ? ????? ? ??????? ? ???? ? ???????????? ? ????????? ? ??? ? ?????BEI? ? ?????? ? ??? ? ??? ? ??? ? ?????? ? ????? ? ????????? ? ????? ? ???? ? ?????????????? ? ??????????? ? ??????? ? ?????? ? ?????? ? ?????? ? ?????? ? ?????? ? ?????? --------------------------------------------------------------------------- ????????? ?????????????????????????????? ???????????????????????????????????????? ????????????. ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????? ???????????????????????????????????????? ?????????????UT?????????????????????????? ???????????????????????????????????????? ???????? ------------------------------------------------------------------------------- ?????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Fri Aug 27 19:30:53 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Aug 2010 21:30:53 +0200 Subject: gdbstub initial code, v6 Message-ID: <20100827193053.GA31988@redhat.com> Changes: - adapt to "no more utrace changes". Whatever I think about utrace I have to agree, it is not practical to change utrace now - attach to the thread-group with the dead leader - fix the double-attaching bug - do not assume we can trust pid_task(), the tracee can be reaped even if it can't pass ->report_death() - size_t is unsigned! -EAGAIN from ->read() makes this fd unusable from rw_verify_area() pov Next: report signals. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_code; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static inline void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (list_empty(&thread->t_stopped)) return; WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH)); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); WARN_ON(thread->t_stop_state & T_STOP_ACK); if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; ret = true; thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! thread->t_stop_code = current->exit_code; // XXX: temporary, for ugdb_add_stopped() thread->t_stop_state = T_STOP_REQ; ugdb_add_stopped(thread); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { /* * (gdb) interrupt & * (gbd) interrupt -a & * * make sure -a actually works if it races with clone. */ if (all && !(thread->t_stop_state & T_STOP_ALL)) { /* * We hold ugdb->u_mutex, so we can't race with * ugdb_report_clone(). But we need spinlock to * avoid the race with ugdb_add_stopped() which * can change ->t_stop_state in parallel. */ spin_lock(&ugdb->u_slock); thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); } return 0; } // XXX: currently we can do this lockless ... thread->t_stop_state = all ? (T_STOP_REQ | T_STOP_ALL) : T_STOP_REQ; thread->t_stop_code = 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!process_alive(thread->t_process)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!process_alive(process)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!process_alive(process)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, live, code; struct pbuf *pb; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; live = thread_alive(thread); code = thread->t_stop_code; pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } // X9;process:4aee // W0;process:4f1c if (live) { pb_printf(pb, "%sthread:p%x.%x;", "T00", pid, tid); } else { char r; if (code & 0xff) { // XXX: renumber signal! code &= 0xff; r = 'X'; } else { code >>= 8; r = 'W'; } pb_printf(pb, "%c%x;process:%x", r, code, pid); ugdb_destroy_process(thread->t_process); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Fri Aug 27 19:37:08 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Aug 2010 21:37:08 +0200 Subject: [PATCH v2] utrace_barrier(detached_engine) must not sping without checking ->reporting In-Reply-To: <20100819135638.GA2230@redhat.com> References: <20100818172704.GA2230@redhat.com> <20100819135638.GA2230@redhat.com> Message-ID: <20100827193708.GA32476@redhat.com> I forgot about this one... Once again, I agree with no more changes, but could you comment this patch? This looks like a bug to me. If it is not, I'd like to understand the rationale behind the "spin until s/detached/NULL/". On 08/19, Oleg Nesterov wrote: > > ------------------------------------------------------------------------------- > [PATCH v2] utrace_barrier(detached_engine) must not sping without checking ->reporting > > If engine is detached (has utrace_detached_ops), utrace_barrier(engine) > spins until engine->ops becomes NULL. This is just wrong. > > Suppose that utrace_control(DETACH) returns -EINPROGRESS, now we should > call utrace_barrier(). However, it is possible that -EINPROGRESS means > we raced with, say, sys_sleep(A_LOT) doing report_syscall_entry(). > > If start_callback() notices utrace_detached_ops and sets report->detaches > everything is fine. But it is quite possible that this doesn't happen, > and in this case utrace_barrier() will spin "forever" waiting for the > next utrace_reset(). > > Change get_utrace_lock() to succeed if the caller is utrace_barrier() > and ops == &utrace_detached_ops. I do not see any reason why this case > should be special from utrace_barrier's pov. It can just check > ->reporting and return 0 or do another iteration. > > Note: we should also reconsider() utrace_barrier()->signal_pending() > check. Also, it is not clear why utrace_barrier() needs utrace->lock, > except to ensure it is safe to dereference target/utrace. > > Signed-off-by: Oleg Nesterov > --- > > kernel/utrace.c | 11 ++++------- > 1 file changed, 4 insertions(+), 7 deletions(-) > > --- kstub/kernel/utrace.c~9_utrace_barrier_and_detached 2010-08-18 17:47:53.000000000 +0200 > +++ kstub/kernel/utrace.c 2010-08-19 15:33:06.000000000 +0200 > @@ -416,23 +416,21 @@ static struct utrace *get_utrace_lock(st > return ERR_PTR(-ESRCH); > } > > - if (unlikely(engine->ops == &utrace_detached_ops)) { > + if (attached && unlikely(engine->ops == &utrace_detached_ops)) { > rcu_read_unlock(); > - return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); > + return ERR_PTR(-ESRCH); > } > > utrace = task_utrace_struct(target); > spin_lock(&utrace->lock); > if (unlikely(utrace->reap) || unlikely(!engine->ops) || > - unlikely(engine->ops == &utrace_detached_ops)) { > + (attached && unlikely(engine->ops == &utrace_detached_ops))) { > /* > * By the time we got the utrace lock, > * it had been reaped or detached already. > */ > spin_unlock(&utrace->lock); > utrace = ERR_PTR(-ESRCH); > - if (!attached && engine->ops == &utrace_detached_ops) > - utrace = ERR_PTR(-ERESTARTSYS); > } > rcu_read_unlock(); > > @@ -1286,8 +1284,7 @@ int utrace_barrier(struct task_struct *t > utrace = get_utrace_lock(target, engine, false); > if (unlikely(IS_ERR(utrace))) { > ret = PTR_ERR(utrace); > - if (ret != -ERESTARTSYS) > - break; > + break; > } else { > /* > * All engine state changes are done while From mamybello at rediffmail.com Fri Aug 27 15:25:50 2010 From: mamybello at rediffmail.com (Mamy bello) Date: 27 Aug 2010 15:25:50 -0000 Subject: =?utf-8?B?SGVsbG8=?= Message-ID: <20100827152550.10475.qmail@f6mail-145-152.rediffmail.com> My Dearest One , I am writing this letter with due respect and heartful of tears since we have not know or met ourselves previously, I am asking for your assistance after I have gone through your profile that speaks good of you. I want to find out if it's possible for you to deal with individual as to investment. I came across your profile and I feel it's highly reputable that is why I pick an interest getting across to you in respect of investment at my disposal. I will be so glad if you can allow me and lead me to the right channel towards your assistance to my situation now. I will make my proposal well known if I am given the opportunity. I would like to use this opportunity to introduce myself to you. My late father Dr Ousman Bello was chairman managing director, RUDOLPH & SONS INDUSTRIAL COMPANY in my capital (Khartoum) in my country, Sudan, and he was also the personal adviser to the former head of state before the rebels attacked our house one early morning and killed my mother and father in a cold blood during the last war in my country. It was only me that is alive now and i managed to make my way to a nearby country Senegal where i am living now as a refugee. Please bear with me for sending this letter to you surprisingly. My name is ( Miss.Mamy Bello) age 26 years old a young girl from Sudan in West Africa as i told you before. The main reason why I am contacting you now is to seek your assistance in the area of my future investment and also for a help hand over some huge amount of money in my possession. This money (US 5.6 Million dollars) is deposited in a bank some years ago by my father he made me the sole beneficiary I am now asking you to stand on my behalf, to stand as my partner and in time of the claim and investment as well. I want to go back to my studies because i only attended my first year before the tragic incident that lead to my being in this situation now took place. As I have mention earlier I will make the procedure to this issue to be well know to you, if I am given the opportunity to do so. Please attach your direct and full information as you reply to me. i will be waiting to hear from you. Best regard Miss. Mamy. -------------- next part -------------- An HTML attachment was scrubbed... URL: From atom at bjoern.us Sat Aug 28 22:07:29 2010 From: atom at bjoern.us (Iarossi Osmers) Date: Sat, 28 Aug 2010 19:07:29 -0300 Subject: Your wife photos attached Message-ID: <4C79876A.6060502@bjoern.us> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: traitor.zip Type: application/octet-stream Size: 11295 bytes Desc: not available URL: From cbht at njki.com Mon Aug 30 02:35:54 2010 From: cbht at njki.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Mon, 30 Aug 2010 10:35:54 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyfqy+rzGu67T687vwc+/2NbG?= Message-ID: <201008300235.o7U2Ziku005937@mx2.redhat.com> utrace-devel?????????????????? ??????????2010??9??16-17?? ???? ??????????2010??9??18-19?? ???? ??????????2010??10??21-22?? ???? ??????????2010??10??23-24?? ???? ?????????????????????????????????????????????????????????????????????????????????????????????? ??????2600??/???????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc2010 at 126.com?????? =============================================================================== ??????????????????????????????????????????????????,??????????????????????????????,???????????????????? ????????.),????????(PMC)????????????????????????????????????.???????????????????????????????????????? ????????????????????????????????????????????????????????????????.???????????????????????????????????? ??????:????????????????????????????????????(??????????????????????)????????????????????????,?????????? ???????????X???????????? ================================================================================ ????????????60/40??????????(????60%,????40%)??????????/??????????????????/???????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????,??????????????????.???? ??????????????????,????????????. ??????????????????????????????????????????????????/?????????????????? ?????????????????????????????????? ================================================================================= ????????????????????????,??????????????????+??????????????????+?????????? ?????????? ????????????MBA,??????????????????????????????????????(AMA)????????????????????????/???????? /????????/????????EMBA????????????????..?????r?????A???s?@????2004/2005/2006?????????????????????????? ????????????????????????????????????????.??????????????????????????????,????????????????????/?????????? ??. ????????????????????????????????????????/??????4524??????????(??2006??)???????????????????????????? ????????????.??????????????????????????????/?????????????????????????????????r?????A?????????????????? ??2004/2005/2006????????????????????????????/?????????F??????????????(????/JIT-????/????????/??????. ????????????????,????????????????,??????????????,??????????????????????,????????????,?????????????????? ??????????????????.????????????????????????????????????????????????????????????????????. ??????????????????????????????????????,????????????????????????????????????????????????/????????????.?? ????????????????????????????????????????????????????????????????????????????.????????.??????????.?????? ????????.??????????????????/??????????.??????(MULTEK)/ ??????????Jabil??.?????????????????????????????? ???????????????? ?????????F.?????????? ============================================================================== ???????? ?????? ?N??????/???b????/???????????????????? ??.???b????/??????????????????---?????????????????? ??.???b????/???????????????????? ?? ?????????????????b/???????????????? ??.???b????/????????????????----??????????????????????/????????--???? 4 .??????????????????????????- ?? ????????????VS??????????VS???????????????? ?? ????????????????/????????/??????????????????/?????????????? ?? ????????????????????????????????(????)-----?????????????? ?? ????????????/?????????????????????????????????? 5.?????????????????????????????????????????? ?? ?N???????????D?D?????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? 6.???????????????????????????D?D????????????????????????(push)????????????????????(pull)???????????? ?? ?????????????I?????Y??.??????????Schneider?????????????????? ?? ????????????????????????????????-----????????????/????/???????? ?? ?????????????????????????????????????????? ?? ???????????????????????????????????? ?????? ????????????----??????/???????????????????? 1.??????????????????????---????/?????????????????????? ?? ??????????????????????????????????????- ?? ???????????????????????????????????????? ?? ??????????????????????????????????????????/???????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ?????????????I?????????????????????????????????????????????????????????????????? ?? ???????????????I?????Y??????????ultek???b???????????????????? ?? ??????(????????)ERP??SAP/R3?????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ?????????????I???????I??????(push)???????????????? ?? ??????????????????????????(pull)????????????????????????????????- ?? ????????????????????????------?????????????????????? ?? ????????????????????????????/???????????????????????? ?? ??????????????????????????/????????????????????/????????????????????/???????????????????????????? ?? ????????????????????????????????????/????????/??????????????????/?????????????????????????????? 2.???b????????????(????)????---?????????????? ?? ??????/??????????????(JIT)???????????????????? ?? ??????????????(JIT)???????????????????? ?? ??????????BOSCH?????????????????????????????????????????? ?? ??????????BOSCH???????????????????????????????????????????? ?? ?????????????I???????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ??????????????????????????(JIT)?????????? ?? ???????????????????????? ?? ????????IE???????????????????????????? ?? ?????????????????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ??????????????---?????????????????????? ?? ???????????????????????????????? ?? ????PE/IE?????????????? ?? ??????????/????????????????---?????? ------?????????????????????????? ?????? ???????????????? 1.???????????????? ?? ?????????????????????????????????????????????? ?? ???????????????????????????????????????????????????? 2.??/???????????????????????????????????? ?? ???????????????????????????????????????? ?? ???????????????????????????????????????? 3.?????????????????????? 4.??????????????????????---????????/???????????? ?? ??????????????2007/04???????????????????????? ?? ??????????????????-----?????????????????? ?? ??????????????????------?????????? 5.??????????????????????????????---- ?? ??/??????????????????????????????????--????????????????????/???????????????????????????? ?? ?????????????????? 6.???????????????? 7. ????????????????????------????/????/???? ?? ???????????????????? ?? ??????????????????????????????????????????---?????????????? ?? ????????LED????????????????????????????---???????? 8. ????????????????????????--???????????????????????? 9. ??????????????????--???????????????????????? 10.????????????????????????????/????????????????????????--------???????? 11.????????????????????????????????/???C????????????--------???????? ????????????????????????????????-----??????(OEM)/??????(ODM) 1.??????????????????????----??????????????????(??????????????????) ?? ??????????????????MRP??????????(????)???????? ?? ??????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????????? ?? ????????????????????????(????????)ERP??SAP/R3???????????????????????????????????? ?? ??????????????????ERP-???????????????????????????????????? ?? ???????????Y?????????????????????????? ?? ???????????????I?????Y?????????????????????????D?D???????? ?? ?????????????????I???IERP-ORACLE????????????/?????????????????? ??.???????????????????????? ?? ?????????????? ????????????????--?D?D?????????Y?????????????????????????? ?? ??????????????????????????/?????????Y???????????????????? ?? ??????????????????????/????????????????--?????????????? ?? ????/TTi/??????????????/????????????????????/???????????????? 3.????????????????(????)???????? ?? ????????---???????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ??????????????????????????????/?????????????? ?? ??????????????????????????????????????????????????????-- ?? ??????????????/?????? ?? ?????????????????????? ?? ???????????????????????????????????? ?? ??????????BOSCH????????????????????????/???????????? ?? ABB/AREVA???????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????? ?? ??????????????????????????/????/?????????????????????????? ?? ??????JIT???????????????? ?? ????????????????????????????????????Milk-Run?????????? ?? ??????????JIT??????---????????????????????/????/????/???? ?? ???????????????????????????????????????????? ?? ????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????? ?? ????????????????VMI??----???????????????????????? ?? ??????????VMI?????????? ?? ??????????????(????)??????????VMI?????????????????? ?? ????????????????????????VMI ???????????????????? ?? ??????????????????????--????????????????/???????????? ?? ?????????????????? ?? ???????????????????????????????????????????????????? ?? ??????????ERP-ORACLE????SCP?????????????????????? ?? ????????????????????????????????????(EDI)???????? 4.???????? ?? ???????????????????? ?? ?????????????????? ?? ????????????????????????????????????????????????????????????????????----?????????????? ?? -????????????????????MTO /ROP ????????/??????????MOQ???????????????? ?? ???????????????????????????????????????????????????????? ?? ???????????????????????????????????????????? ?? ??????????????????????????????/??????/?????????? ?? ????/?????????????????????????????? ?? ?????????????????????????????? 5.?????????????????????????????? ?? ????:?????????????????? ?? ????/????????,??????????????????????????????- ?? ????????????????--????????/????????/???????? ?? ????/?????????????? ------------------------------------------------------------------------------- ??PMC??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From oleg at redhat.com Mon Aug 30 18:58:50 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 30 Aug 2010 20:58:50 +0200 Subject: gdbstub initial code, v7 Message-ID: <20100830185850.GA1132@redhat.com> Changes: - report signals. A bit more code changes than I expected. - implement QPassSignals, trivial. Note: $CSIG is not supported yet, and I am not sure I understand how it should work. Next time... -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: case UTRACE_SIGNAL_REPORT: if (ugdb_stop_pending(thread)) return UTRACE_STOP | UTRACE_SIGNAL_IGN; return action; default: break; } signr = info->si_signo; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) return UTRACE_STOP | UTRACE_SIGNAL_IGN; /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". */ return UTRACE_STOP | UTRACE_SIGNAL_HOLD; // XXX: is this correct ??? check utrace_get_signal... } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { WARN_ON(*pkt == '$' || *pkt == '#' || *pkt == '%'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; mutex_lock(&ugdb->u_mutex); if (ugdb->u_cur_hc) if (ugdb_cont_thread(ugdb->u_cur_hc, false) > 0) rc = "OK"; mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) return "E01"; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From jan.kratochvil at redhat.com Mon Aug 30 19:20:40 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 30 Aug 2010 21:20:40 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100830185850.GA1132@redhat.com> References: <20100830185850.GA1132@redhat.com> Message-ID: <20100830192040.GA15431@host1.dyn.jankratochvil.net> On Mon, 30 Aug 2010 20:58:50 +0200, Oleg Nesterov wrote: > - report signals. A bit more code changes than I expected. BTW not sure if it is already the right time for it but to keep ugdb on-par with my linux-nat's re-post today (still not accepted in FSF GDB) [0/9]#2 Fix lost siginfo_t http://sourceware.org/ml/gdb-patches/2010-08/msg00480.html ugdb should support qXfer:siginfo, currently accessible only via $_siginfo print/set, though. Thanks, Jan From hju at bvef.com Tue Aug 31 03:23:09 2010 From: hju at bvef.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Tue, 31 Aug 2010 03:23:09 -0000 Subject: =?GB2312?B?QzJ1dHJhY2UtZGV2ZWy8qNCnv7y6y/TfS1BJK0JTQw==?= Message-ID: <201008310322.o7V3MhHl008446@mx1.redhat.com> utrace-devel?????KPI+BSC ?? ?????2010?9?3-4? ?? ?????2010?9?9-10? ?? ?????2010?9?17-18? ?? ? ??2800?(???????????????????????) ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ???????600?/?;??800?/?(??????????????) --------------------------------------------------------------------------------- ????????????? ???????????????????????????????????? ????????????????????????????????? ???????????????? ??????????????????? ??????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????? ???????????????????????????????????????????????? ??????????????????????? ?????????????????? ????????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????????????????????????????????? ?????????????????????? ???????????????? ???????????????????????????KPI???????????????????? ???????????????????????????????????????????????? ???KPI???????????????????????????????????????????? ???KPI?????? ??????????????????? ???????????????? ??????????????????????????????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ???????? ????????????????????? ?????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????????????????????? ??????????????????????????????????????? --------------------------------------------------------------------------------------------- ????? ????KPI???????????????? 1?????????????????? ??????????????????? ??????????? ??????????? ???????????? ???????????? KPI??????????? 2????????????????????? ???????????? ?????????A? ?????????????? 3????????KPI??? ??KPI?????????? 1????????? 2?KPI?????????????? ???????????????????? ????????????????????? ???????????????????? 3?KPI??????????KPI????????????????????????????????????? 4????????????????? ????KPI???????? ?????????KPI???????????????????????????????????????????KPI??????? 1???????????????????????KPI????????????????? 2?????????????? 3?????????? ??????? 1????????????????????????????? 2????????????????????????? 3?????????????????????????????????????????????? 4??????????????? 5???????????????????????????????? ??????KPI KPI??????????????????????KPI?????????????????kpi???????????????????? ???????????????KPI???????? 1?????KpI??????????????? 2??????2????? 3?????????KPI???3?????? 4???KPI?????????????????????????????????? ????????? ??????????????????????????????KPI?????KPI? 1????????KPI 2????????????????? 3?????????????????? 3??????????????????????????? 4???????KPI??????? ????????KPI????? ???????????????????????????????????????????????? 1????????? 2?????????? 3.?????????? 4???????????????? 5?????????????????????? 6???????????????? 7???????????????????????????????KPI?????? ????????? ????????????????????????????????????????????????????????? 1????????????? 2????????? 3?????????????? 4?????KPI????????????? ????????? ???????????????????????????????????????? ???????????????????????????????????????? 1?KPI????????? 2?????????????? 3????????????????? ????????? 1?????????? 2????? 3?????????? 4??????????????????????????? ??????????????????? ????KPI???????????????????KPI???????????????? 1????????????????????? 2??????? 3????????????? 4??????????? ---------------------------------------------------------------------------------------------- ??????? ??---?????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ?????????????????????????????????? ????????????????????????????????????????? ????????KPI??????????????BSC???????????????? ???????????????? ???????????????????????????????????TCL????? ????????????????????????????????????????? ???????????????????????????????? =============================================================================== ??????KPI+BSC ????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From jan.kratochvil at redhat.com Tue Aug 31 07:20:48 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 31 Aug 2010 09:20:48 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100830192040.GA15431@host1.dyn.jankratochvil.net> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> Message-ID: <20100831072048.GA26362@host1.dyn.jankratochvil.net> On Mon, 30 Aug 2010 21:20:40 +0200, Jan Kratochvil wrote: > On Mon, 30 Aug 2010 20:58:50 +0200, Oleg Nesterov wrote: > > - report signals. A bit more code changes than I expected. > > BTW not sure if it is already the right time for it but to keep ugdb on-par > with my linux-nat's re-post today (still not accepted in FSF GDB) That's not true, this functionality needs no gdb/remote.c changes and its correctnes relies just on ugdb (and it is probably not a problem for ugdb). > ugdb should support qXfer:siginfo, currently accessible only via $_siginfo > print/set, though. Still sure this feature should be also implemented one day. Thanks, Jan From premier_05 at masteremarketing.com.br Tue Aug 31 07:06:12 2010 From: premier_05 at masteremarketing.com.br (Premier Training) Date: Tue, 31 Aug 2010 04:06:12 -0300 Subject: =?UTF-8?B?UFJFTUlFUiBUUkFJTklORyAtIFJldGVuw6fDtWVzIG5hIGZvbnRlIC0gKDExKSAzMDYwIC0gMjEwMA==?= Message-ID: <990a925ba3570f17ef521072d068175c@187.45.206.57> An HTML attachment was scrubbed... URL: From bj2008 at chsi.com.cn Tue Aug 31 10:55:47 2010 From: bj2008 at chsi.com.cn (=?GB2312?B?uN/Qvbmk1/fWsM67vfrJ/czhsM7WsLPGu6e/2sfhy8m2vLjjtqg=?=) Date: Tue, 31 Aug 2010 18:55:47 +0800 Subject: =?GB2312?B?1f255s2z1dDRp8D6uMSx5MTjw/zUyw==?= Message-ID: <201008311055.o7VAtnrq012392@mx1.redhat.com> ?????????? ?? ?? ?????????????? ???? ???? ???? ???? ???? ???? ????????????????? ????????????????????????????????????????????????????????,????????????????? ??????????????????????????????????????????????????????????????????????????? ???????????????????????????????????!? ?????????????????? ???????????????????????????????,????,????????????????? ?????????????? ??????????????????????????????????,???????????????????????!! ??????: ??????: ?????(??,??)????????,????(??,??)????,????(???,???)?????????(??,???),??????? ????,???,???,?????????? !! ???????,?????????????,??????????,??????,??,??,??,??????, ????? www.chsi.com.cn ?????????? ???????????????: www.chsi.com.cn/xlcx/index.jsp ??????????????????13261188788 ??? ? ????????????????????????????,????????,?????!! ????? 1. ??????? ????????, ???????????, ??? ?? ??? ?? ?? ?? ?? ?? ? 2.????????? ????? ????? ????? ?3500?-10000??? 3.??????? 3-5????? ????? 1.???????: ?????????????, ?????????????????? 2.??????????????????? ?? ?? ?? ?????) , ??(?? ?? ?????), ????(????)??, ????, ???? 3.????????????????20????????????? ????: ?????????????????20%????????????????????????????? ????? www.chsi.com.cn ?????????? ???010-82336088 ???????????????: www.chsi.com.cn/xlcx/index.jsp ?????????????????? 13261188788 ??? ? ????????, ??????,????????????????!! ???????????????????????????????????? ?????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????? ????????? ?? ???????????????????????????????????? ??????????????? ?????????????30????????????? ???? ?????????????????????1205? ????? www.chsi.com.cn ?????????? ???????????????: www.chsi.com.cn/xlcx/index.jsp ?????????????????? 13261188788 ??? From jenetkoneh at aim.com Wed Sep 1 03:49:10 2010 From: jenetkoneh at aim.com (jenetkoneh at aim.com) Date: Tue, 31 Aug 2010 23:49:10 -0400 (EDT) Subject: Nice To Meet You, Message-ID: <8CD179FC53A38AD-790-7147@webmail-m021.sysops.aol.com> Nice To Meet You, My name is Miss jenet koneh, As I whisper my prayer tonight and went into search for a nice friend at google that is(internet) I came across your contact,My mind and my heart told me to contact you for friendship, A friend who truly understand his or her friend and share their feelings together. please kindly accept my request, I believe that distance or age can never be a barrier but let's love connect us because love is a bridge that connected far distance to be close to each other, I will send my pictures to you immediately i receive your reply at my email address jenetkoneh at aim.com yours In Love, jenet jenetkoneh at aim.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From my at zj.com Wed Sep 1 15:57:31 2010 From: my at zj.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Wed, 1 Sep 2010 23:57:31 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVszve149a00NDBpg==?= Message-ID: <201009011557.o81FvS2Z022610@mx1.redhat.com> utrace-devel????? ?????2010?09?27-28? ?? ?????2010?09?29-30??? ????2680?????????????????????????????? ??????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ?????????????????????????????200????????????????? ??3700????????500?????1000??????2000???????5000?????????? ??????????????????????????????? ??????????????????????????????????????????????? ????????????????1030??????????????5????????????90%? ??????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????? ------------------------------------------------------------------------------------------- ????? 1.????????????????????????? 2.???????????????????? 3.????????????????????????????????? ---------------------------------------------------------------------------------------------- ????? 1.????????????????????????????????????? 2.??????????????????????????????????????? ------------------------------------------------------------------------------------ ????? ????????????? ??? ???????????????? ???????????? ???22??? ??????? ???????????? ?????????? ????????????????? ??????????????? ????????? ?????????????? ????????????? ????????????? ???? ??????? ???????? ????????????? ?????????? ?????????? ?????????? ????????????? ?????????????? ????????? ????????? ????????? ???????????????? ????????????? ?????????????? 80/20?? ???????? ?????? ????? ????????????? ??????????????? ?????????? ?????????????? ?????????? ???????????? ???? ???? ???? ?????????????????? ??????????? ???????????? ????????????? ????????? ??????????? ????????? ???? ???? ???? ????? ???????? ??????? ??????????? ???? ???? ???? ???16??? ???24??? ??????? ????????????? ????????????????? ?????????????? ???GE?????????? ????????????? ??????????? ????????? ????????? ????????? ????????? ????????????? ???????????? ???????????? ???????????? ?????????? ??????? ???? ???? ????????? ????????????????? ?????????????? ????????????? ????????????? ????????????? ????????????? ???????????????? ??????&??????? ??????????????? ??????? ??????? ??????? ??????? ??????????? ????????????? ????????????????? ?????????? ??????????????? ???????????? ????????????? ???????????? ?????????????????? ????????????????? ???????? ???? ???? ???? ???? ???? ????????4P?? ?????????? ??????????? ?????????? ??????????????? ??????????? ??????? -------------------------------------------------------------------------- ????????????GEC??????????????PTT???????????? ???????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????04?????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ???????????????????????????HR??????????????? ???????? ??????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????TCL???????? ????????? -------------------------------------------------------------------- ????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From erh at ufd.com Wed Sep 1 17:02:02 2010 From: erh at ufd.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Thu, 2 Sep 2010 01:02:02 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsz/rK29b3udy53MDtxNzBpszhyf0=?= Message-ID: <201009011702.o81H20Jv027104@mx1.redhat.com> utrace-devel????2?1??? ?????2010?09?04-05? ?? ?????2010?09?11-12? ?? ?????????????????????????????? ?????2880?(2??,1?? ??,?????,???,???) ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ???? 1.?????????????????????????????? 2.???????????????????????????? 3.???????????????????????????????? 4.??????????????????????????? 5.?????????????????????????? 6.??????????????????????????? 7.??????????????????????? 8.?????????????????????????????? 9.????????????????????????????? 10??????????????????????????????????? 11. ??????????????????????????? 12. ?????????????????????????????? ?????????????????????????????????????? ???? 1.2?????61?????????? 2.?????????????????????? 3.????????????????? 4.???????????? ????????????????????? ??????????????????? ????????????????????????? ?????????????????????????????????????? ???? ????????????????????????????????????? ????????????????????????????? ?????????????????????????????????????? ?????? ?? 1.????????????????? 2.??????????????? 3.??????????????????? 4.?????????????????? 5.?????????????????????? ????? ?????----- ??????????????? ?????????????????? 1????????? ??????? 2???????? ? ??? 3???????????????? ? ???? 4??????????? ??? ???? 5???????? ????? ???? 6????????????? ? ???? 7????????????? ?????? 8?????????? ???? ???? 9??????????????? ? ???? ????? ????-----??????????????? ?????????? 1.??????????????????? 2.??????????????????? 3????????????? 4????????????????????? 5????????????????? 6???????????????? 7??????????6???? ???????? ?? ????????????????? ? ??????????????????? ? ?????????????????? ? ????????????? 1?????????????????? 2???????????????????? 3??????????????? 4??????????????? 5????????????? 6??????????????????? ??????????????????????? ?????????????????? ???????? ??? 1.???????????????????????? 2.????????????????????? 3.????????????????? 4.???????????????? 5.??????????????????? 6.??????????????????????????? ???????????????? ????????????? 1.??????????????? 2.????????????? 3.??????5???? ?????????????????? 1.??????????????????????? 2.????????????3???? 3.???????3???? ???9??? 4.??????6??? ???????????? ????????6???? ????????????? ?? ???????????????? 1.??????????? 2.??????????5??? 3.?????????7???? 4.??????????6???? 5.????????8??? 6.????????7??? 7.????5????? ??? ???????10???? ???? ??????? 1.???????????????? 2.??????????????????? ???????????????????????? ???????????3??? 3.??????????????? ???????????????? ??????????????????? ????????5??? ??????????????????? ??????????? 4.?????????7????? ???? ???? 1.?????????????????? 2.???????????????????? 3.???????????????????? 4.???????????????? 5.??????????????? 6.????????????????? ???? ???????? 1.??????????????????? 2.????????????????? 3.???????????????? 4.???????????????? 5.????????????????? 6.?????????????????? ??????????4??? ?????????????????????????????????????? ????????? ????????????? ???????????????? ????????????????? ???????????????????? ????.????.????EMBA?????? 2000?????????????????????,???????????????? ?????????????,?????????100??????????????? ????????????,?????????,????????????????? ?????????????????????????????? ????? ??????????? ?????????? ???????????? ???????? ????????? ???????????? ??????? ??????????? ????/??????/????/????/????/????/???/??/????/ ??????/????/??????/????/??????/??????/???? ??/?????/??????/?????/???????/?????/??????/ ??????/????/????/????/????/???????/????/??? ?/???????????/??????? --------------------------------------- ?????2?1???????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From atendimento at 001shop.com.br Thu Sep 2 06:32:51 2010 From: atendimento at 001shop.com.br (001Shop) Date: Thu, 02 Sep 2010 03:32:51 -0300 Subject: Venda pela internet! Message-ID: An HTML attachment was scrubbed... URL: From barrialodeiro at hotmail.com Thu Sep 2 11:37:57 2010 From: barrialodeiro at hotmail.com (paula veronica barria) Date: Thu, 2 Sep 2010 08:37:57 -0300 Subject: =?gb2312?B?xOPKx87SyfrD/NbQtcS588jLo6E=?= =?gb2312?Q?s?= Message-ID: ?????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????????????????????45?????????????????????????????????????????????????????11????????????????????????45???????????????? ????????? ??????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? ?????????????????????? NO NO NO ??? ???????????? ???????????????????100%???? ??????????? ??????? 1????3???? 248???????? 2????????????????????????? 3?7 ??????????????????? ? 4????????????????????????????????? 5????3???????????????14???1000????240000? ? 6?????????????????? ???????????? 7????????????????????????????????? 8?9 ?????????? ????????????????????? ????????? ???????????????????????????????????????????????????? ????????????????????????????????? ????????????????????????? ????? ??????????????????????????????? ????????????2?2????????????? ?????????? ???? ???24????????400--6868---772???? ????????????????????????13764954168 ????????????????????????? ????????? ????????????????????????? ps????????3?????????????????????? 48 ????? ????????????????????????????????????????????????????????????????????? PPS???????????????????????????100??????????????????????50?????????????72???????????????? PPPS?????????????????????????.??????72????????????????????????? PPPPS??????????????????????????????????????????????????????????????? ????????????????????1000?????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Thu Sep 2 19:36:34 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 2 Sep 2010 12:36:34 -0700 (PDT) Subject: [PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case In-Reply-To: Oleg Nesterov's message of Thursday, 26 August 2010 18:57:28 +0200 <20100826165728.GA20425@redhat.com> References: <20100814023128.GA9236@redhat.com> <20100817001308.D335D4007E@magilla.sf.frob.com> <20100817115534.GA30214@redhat.com> <20100819211131.9862E40080@magilla.sf.frob.com> <20100826165728.GA20425@redhat.com> Message-ID: <20100902193634.C795940465@magilla.sf.frob.com> > > When utrace->reap is set, it means release_task() has been called. The > > API caller has no way to know reaping hasn't already begun--except if > > its report_death callback has not returned yet. > > No! the task can be already reaped even before ->report_death() was > called. The task_struct itself can't go away, but that is all (perhaps > you meant this). Yeah, that's kind of what I meant. More precisely, I just had in mind the report_reap callback as the utrace user's idea of "reaped". > And this is the problem for ugdb. Damn, I knew this, that is why > ugdb_process_exit() doesn't try to read ->group_exit_code. Still I > managed to forget that this has other implications. Yeah, I hadn't thought about those implications for what a report_death callback might want to access. For group_exit_code at least, it should be resolved by the 2.6.35 change in the lifetime of signal_struct. > I am not sure. I had another reason in mind to check reap && !death in > get_utrace_lock(), synchronization with ->report_death() callback. > > But OK. Let's forget about more utrace changes for now. Agreed. Thanks, Roland From roland at redhat.com Thu Sep 2 19:50:53 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 2 Sep 2010 12:50:53 -0700 (PDT) Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: Oleg Nesterov's message of Thursday, 26 August 2010 19:13:55 +0200 <20100826171355.GB20425@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> <20100826171355.GB20425@redhat.com> Message-ID: <20100902195053.2DDD140465@magilla.sf.frob.com> > But probably we need utrace_detached_ops->report_reap() anyway. > ->report_death can return UTRACE_DETACH, and after that utrace_report_death() > can skip utrace_reset() and do ->report_reap(). Yeah, that's a good point. There's no good reason to do a special case check for detached_ops there rather than just having the no-op report_reap hook. > > If an engine used UTRACE_INTERRUPT without having first set QUIESCE, > > then it has no rightful expectation of getting any callback. > > Hmm. This is certainly new to me. Could you confirm? Well, I didn't say it precisely correctly. UTRACE_INTERRUPT serves two purposes. First, it just interrupts things like a signal would. You could use that on its own without even tracing any events at all, just do achieve fault injection or similar. Second, it's like UTRACE_REPORT. If you do have some other event bits set, then you can expect/rely on getting those normal events "soon" if they would otherwise have happened--i.e., if you know it's blocked in a syscall, and you have UTRACE_EVENT(SYSCALL_EXIT) set, then you can expect to get a report_syscall_exit "soon". (But, it's always possible to race with the syscall finishing on its own, or being interrupted by an outside signal, so that exit might have come before your utrace_control call if you were not otherwise synchronizing with your established report_syscall_exit callback.) As with UTRACE_REPORT, after UTRACE_INTERRUPT you can expect to get some report_quiesce callback even if there is no other event you were tracing that happens. For this to actually happen, you need to have UTRACE_EVENT(QUIESCE) set. So, it is technically kosher enough to use UTRACE_INTERRUPT without UTRACE_EVENT(QUIESCE) set, if you really know the situation and are sure about all those caveats above. But, it's only UTRACE_EVENT(QUIESCE) that gives you any expectation of an "extra" callback for "no event" from either UTRACE_REPORT or UTRACE_INTERRUPT. (And since that is the sole possible purpose of UTRACE_REPORT, we diagnose a utrace_control call like that.) Thanks, Roland From oleg at redhat.com Thu Sep 2 20:06:32 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 2 Sep 2010 22:06:32 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100831072048.GA26362@host1.dyn.jankratochvil.net> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> Message-ID: <20100902200632.GA23692@redhat.com> Sorry for the delay, I was distracted. Trying to switch back to ugdb. On 08/31, Jan Kratochvil wrote: > > > ugdb should support qXfer:siginfo, currently accessible only via $_siginfo > > print/set, though. > > Still sure this feature should be also implemented one day. Yes sure. This should be simple, although I didn't expect qXfer needs remote_escape_output() and x86_siginfo_fixup(). I assume that qXfer:siginfo:read always mean Hg thread. It is not clear to me what should ugdb report if there is no a valid siginfo. linux_xfer_siginfo() return E01, but gdbserver uses SIGSTOP to stop the tracee, so it always has something to report. But ugdb stop the tracee somewhere else, not in get_signal_to_deliver() path. Likewise, it is not clear what should ugdb do if gdb sends $CSIG in this case. But this all is minor, I think. I was going to send v8 which implements qXfer:siginfo:read and continue with signal, but (oh, as always) hit the unexpected problems. To the point, I had to add printk's to utrace.c to understand what is wrong. Hopefully tomorrow. Oleg. From oleg at redhat.com Thu Sep 2 20:33:33 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 2 Sep 2010 22:33:33 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100902195053.2DDD140465@magilla.sf.frob.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> <20100826171355.GB20425@redhat.com> <20100902195053.2DDD140465@magilla.sf.frob.com> Message-ID: <20100902203333.GA24757@redhat.com> I was going to ping you ;) This is connected to the problem I hit today. Despite the fact I already complained about utrace_get_signal() && QUIESCE, I forgot about this and figured out it doesn't work in practice. On 09/02, Roland McGrath wrote: > > > > If an engine used UTRACE_INTERRUPT without having first set QUIESCE, > > > then it has no rightful expectation of getting any callback. > > > > Hmm. This is certainly new to me. Could you confirm? > > Well, I didn't say it precisely correctly. UTRACE_INTERRUPT serves two > purposes. First, it just interrupts things like a signal would. You could > use that on its own without even tracing any events at all, just do achieve > fault injection or similar. Second, it's like UTRACE_REPORT. Yes, this is clear. > As with UTRACE_REPORT, after UTRACE_INTERRUPT you can expect to get some > report_quiesce callback even if there is no other event you were tracing > that happens. For this to actually happen, you need to have > UTRACE_EVENT(QUIESCE) set. Hmm. I am not sure I understand. If ->report_signal != NULL, then you can't expect ->report_quiesce() after utrace_control(INTERRUPT) ? > So, it is technically kosher enough to use UTRACE_INTERRUPT without > UTRACE_EVENT(QUIESCE) set, if you really know the situation and are sure > about all those caveats above. How? see below. > But, it's only UTRACE_EVENT(QUIESCE) that > gives you any expectation of an "extra" callback for "no event" from either > UTRACE_REPORT or UTRACE_INTERRUPT. Yes, this is clear too. So. Now I am even more confused. First of all, ugdb (at least currently) does not need report_quiesce() and UTRACE_EVENT(QUIESCE) at all. OK, this is not 100% true due to multitracing/etc, lets ignore this. Anyway it makes sense to clear QUIESCE after $c to avoid the unnecessary callbacks. All it needs is ->report_signal(). But, the problem is, it is not called after utrace_control(INTERRUPT) ! You need QUIESCE to ensure report_signal() will be called, and this looks at least strange to me. Once again, I am not asking to change utrace now, but could you explain what is wrong with the patch below? Oleg. --- x/kernel/utrace.c +++ x/kernel/utrace.c @@ -2029,7 +2029,8 @@ int utrace_get_signal(struct task_struct report.spurious = false; finish_resume_report(task, utrace, &report); return -1; - } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + } else if (!(task->utrace_flags & + (UTRACE_EVENT(QUIESCE) | UTRACE_EVENT_SIGNAL_ALL))) { /* * We only got here to clear utrace->signal_handler. */ From jan.kratochvil at redhat.com Fri Sep 3 06:40:08 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 3 Sep 2010 08:40:08 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100902200632.GA23692@redhat.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> Message-ID: <20100903064008.GA16249@host1.dyn.jankratochvil.net> On Thu, 02 Sep 2010 22:06:32 +0200, Oleg Nesterov wrote: > I assume that qXfer:siginfo:read always mean Hg thread. It seems so. > It is not clear to me what should ugdb report if there is no a valid > siginfo. linux_xfer_siginfo() return E01, but gdbserver uses SIGSTOP to > stop the tracee, I find error more appropriate in such case. > Likewise, it is not clear what should ugdb do if gdb sends > $CSIG in this case. Currently GDB does not do anything special, that is if there is siginfo for signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is left the SIGUSR1 siginfo for SIGSEGV? > But this all is minor, I think. As this is being discussed for GDB I would find enough to just make $_siginfo accessible without these details. Thanks, Jan From fche at redhat.com Fri Sep 3 14:17:26 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Fri, 03 Sep 2010 10:17:26 -0400 Subject: gdbstub initial code, v7 In-Reply-To: <20100902200632.GA23692@redhat.com> (Oleg Nesterov's message of "Thu, 2 Sep 2010 22:06:32 +0200") References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> Message-ID: Oleg Nesterov writes: > [...] To the point, I had to add printk's to utrace.c to understand > what is wrong. Hopefully tomorrow. You might wish to try out systemtap for such purposes. It's easy to insert printk-like tracing at almost any point; monitor variables for changes, pretty-print structs, etc. No recompilation/reboot. - FChE From roland at redhat.com Fri Sep 3 19:59:06 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 3 Sep 2010 12:59:06 -0700 (PDT) Subject: gdbstub initial code, v7 In-Reply-To: Jan Kratochvil's message of Friday, 3 September 2010 08:40:08 +0200 <20100903064008.GA16249@host1.dyn.jankratochvil.net> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> Message-ID: <20100903195906.406D5401B3@magilla.sf.frob.com> > Currently GDB does not do anything special, that is if there is siginfo for > signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is > left the SIGUSR1 siginfo for SIGSEGV? The kernel considers this sloppy behavior on the debugger's part. If you inject a different signal, we expect you should PTRACE_SETSIGINFO to something appropriate, or else that you really didn't care about the bits being accurate. If the resumption signal does not match the siginfo_t.si_signo, then the kernel resets the siginfo as if the debugger had just used kill with the new signal (i.e. si_pid, si_uid point to the ptracer). Thanks, Roland From jan.kratochvil at redhat.com Fri Sep 3 20:02:53 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 3 Sep 2010 22:02:53 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100903195906.406D5401B3@magilla.sf.frob.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903195906.406D5401B3@magilla.sf.frob.com> Message-ID: <20100903200253.GA22347@host1.dyn.jankratochvil.net> On Fri, 03 Sep 2010 21:59:06 +0200, Roland McGrath wrote: > > Currently GDB does not do anything special, that is if there is siginfo for > > signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is > > left the SIGUSR1 siginfo for SIGSEGV? > > The kernel considers this sloppy behavior on the debugger's part. If > you inject a different signal, we expect you should PTRACE_SETSIGINFO > to something appropriate, or else that you really didn't care about > the bits being accurate. If the resumption signal does not match the > siginfo_t.si_signo, then the kernel resets the siginfo as if the > debugger had just used kill with the new signal (i.e. si_pid, si_uid > point to the ptracer). OK, that seems to me as the best choice. Sorry I did not test/read it. Thanks, Jan From roland at redhat.com Fri Sep 3 20:10:23 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 3 Sep 2010 13:10:23 -0700 (PDT) Subject: gdbstub initial code, v7 In-Reply-To: Jan Kratochvil's message of Friday, 3 September 2010 22:02:53 +0200 <20100903200253.GA22347@host1.dyn.jankratochvil.net> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903195906.406D5401B3@magilla.sf.frob.com> <20100903200253.GA22347@host1.dyn.jankratochvil.net> Message-ID: <20100903201023.91C7D401B3@magilla.sf.frob.com> > OK, that seems to me as the best choice. Sorry I did not test/read it. No need for you to do so. That's why you have kernel hackers to consult. Thanks, Roland From roland at redhat.com Fri Sep 3 20:37:24 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 3 Sep 2010 13:37:24 -0700 (PDT) Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: Oleg Nesterov's message of Thursday, 2 September 2010 22:33:33 +0200 <20100902203333.GA24757@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> <20100826171355.GB20425@redhat.com> <20100902195053.2DDD140465@magilla.sf.frob.com> <20100902203333.GA24757@redhat.com> Message-ID: <20100903203724.5CF26401B3@magilla.sf.frob.com> > Hmm. I am not sure I understand. If ->report_signal != NULL, then > you can't expect ->report_quiesce() after utrace_control(INTERRUPT) ? Sorry, I used "report_quiesce" as shorthand for "either report_quiesce, or report_signal with UTRACE_SIGNAL_REPORT". > > So, it is technically kosher enough to use UTRACE_INTERRUPT without > > UTRACE_EVENT(QUIESCE) set, if you really know the situation and are sure > > about all those caveats above. > > How? see below. I mentioned the examples. > > But, it's only UTRACE_EVENT(QUIESCE) that > > gives you any expectation of an "extra" callback for "no event" from either > > UTRACE_REPORT or UTRACE_INTERRUPT. > > Yes, this is clear too. Apparently not. ;-) > So. Now I am even more confused. First of all, ugdb (at least currently) > does not need report_quiesce() and UTRACE_EVENT(QUIESCE) at all. OK, this > is not 100% true due to multitracing/etc, lets ignore this. Anyway it > makes sense to clear QUIESCE after $c to avoid the unnecessary callbacks. > > All it needs is ->report_signal(). But, the problem is, it is not called > after utrace_control(INTERRUPT) ! You need QUIESCE to ensure report_signal() > will be called, and this looks at least strange to me. QUIESCE is the only event type for "no event". If you only asked for signal events, then you only get a callback when there is an actual signal event. If you want an extra callback before dequeuing any signal, then that is what QUIESCE is for. > Once again, I am not asking to change utrace now, but could you explain > what is wrong with the patch below? That gives an extra unrequested report_signal callback to every engine that is only interested in some signal event. Consider a "crash-catcher" engine. It would only track UTRACE_EVENT(SIGNAL_CORE) (and perhaps CLONE for its bookkeeping). This engine never asked for a callback before each and every attempt to dequeue any signal, which is what you would give it with your change. Thanks, Roland From oleg at redhat.com Fri Sep 3 22:40:47 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 4 Sep 2010 00:40:47 +0200 Subject: gdbstub initial code, v8 Message-ID: <20100903224047.GA8917@redhat.com> Changes: - fix UTRACE_SIGNAL_HOLD logic - don't assume QPassSignals: passes valid_signal() - implement qXfer:siginfo:read - implement continue with signal. Note: it is still not clear to me what "signal SIG" should do if the tracee did not report a signal (T00 and no signal context). Currently, in this case ugdb just sends this sig to the tracee, this means another TSIG report. Another corner case. Consider (gdb) signal SIG & (gdb) interrupt it is possible (not in practice, I think) that "interrupt" will try to stop the tracee before it handles SIG, in this case the tracee can report TSIG too. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; case UTRACE_SIGNAL_REPORT: if (thread->t_siginfo) { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, but * we can't just stop and lose this signal. */ if (thread->t_stop_state & T_STOP_REQ) goto report; return utrace_resume_action(action) | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | UTRACE_SIGNAL_IGN; return action; default: break; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (sigismember(&ugdb->u_sig_ign, signr)) return action; report: if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". */ return UTRACE_STOP | UTRACE_SIGNAL_IGN | UTRACE_SIGNAL_HOLD; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * Otherwise I do not know what to do, and anyway I don't * think gdb can try to cont a thread which was not reported * as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) return -EINVAL; /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; switch (*cmd++) { case 'C': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *apvm(struct ugdb *ugdb, struct task_struct *task, unsigned long addr, int size) { unsigned char *mbuf; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%d) ENOMEM\n", size); goto err; } size = u_access_process_vm(task, addr, mbuf, size, 0); if (size <= 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; const char *ret = "E01"; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; ret = apvm(ugdb, task, addr, size); /* Too late to report the error*/ if (ugdb_finish_examine(ugdb, &exam)) ; out: return ret; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'C': case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Fri Sep 3 22:57:38 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 4 Sep 2010 00:57:38 +0200 Subject: gdbstub initial code, v7 In-Reply-To: References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> Message-ID: <20100903225738.GB8917@redhat.com> On 09/03, Frank Ch. Eigler wrote: > > Oleg Nesterov writes: > > > [...] To the point, I had to add printk's to utrace.c to understand > > what is wrong. Hopefully tomorrow. > > You might wish to try out systemtap for such purposes. It's easy to > insert printk-like tracing at almost any point; monitor variables for > changes, pretty-print structs, etc. Probably I should try the new versions... Last time I tried systemtap more than year ago. It didn't work for me without the "properly installed" kernel/etc which I don't have. And, I doubt I can insert the probe at the needed line without DEBUG_INFO. > No recompilation/reboot. CONFIG_KPROBE ;) But anyway I agree, systemtap is the great tool. Oleg. From oleg at redhat.com Fri Sep 3 23:09:57 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 4 Sep 2010 01:09:57 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100903064008.GA16249@host1.dyn.jankratochvil.net> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> Message-ID: <20100903230957.GC8917@redhat.com> On 09/03, Jan Kratochvil wrote: > > On Thu, 02 Sep 2010 22:06:32 +0200, Oleg Nesterov wrote: > > > Likewise, it is not clear what should ugdb do if gdb sends > > $CSIG in this case. > > Currently GDB does not do anything special, that is if there is siginfo for > signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is > left the SIGUSR1 siginfo for SIGSEGV? The kernel changes siginfo->si_signo (and updates other fields). So does ugdb. But I meant another case, when the stopped tracee doesn't have siginfo. Currently ugdb just sends this signal to tracee, and then it will be reported to gdb. Not sure if this is right or not, I can change this. (or perhap this doesn't matter, I dunno). Oleg. From bobsled at e-advice.dk Sat Sep 4 06:28:42 2010 From: bobsled at e-advice.dk (Gowell Chhuon) Date: Sat, 04 Sep 2010 03:28:42 -0300 Subject: Your wife photos attached Message-ID: <4C81E62C.6040309@e-advice.dk> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: skewed.zip Type: application/octet-stream Size: 9752 bytes Desc: not available URL: From mldireto at tudoemoferta.com.br Sat Sep 4 03:26:50 2010 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Sat, 4 Sep 2010 00:26:50 -0300 Subject: Semana da Mobilidades - TudoemOferta.com Message-ID: <59c749331c95ee76fe40091d0019bb56@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From premiertraining at masteremarketing.com.br Sat Sep 4 13:02:57 2010 From: premiertraining at masteremarketing.com.br (Premier Training) Date: Sat, 04 Sep 2010 09:02:57 -0400 Subject: =?UTF-8?B?U1VCU1RJVFVJw4fDg08gVFJJQlVUw4FSSUEg4oCTIElOQ0xVSU5ETyBSRUNFTlRFUyBERUNJU8OVRVMgRSBOT1ZPUyBQUkFaT1M=?= Message-ID: An HTML attachment was scrubbed... URL: From ebbing at stcat.org Sun Sep 5 18:50:03 2010 From: ebbing at stcat.org (Paillant Szczygiel) Date: Sun, 05 Sep 2010 18:50:03 -0000 Subject: Your wife photos attached Message-ID: <4C83E1C9.4050305@stcat.org> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: wizardly.zip Type: application/octet-stream Size: 11182 bytes Desc: not available URL: From jan.kratochvil at redhat.com Sun Sep 5 19:41:01 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sun, 5 Sep 2010 21:41:01 +0200 Subject: gdbstub initial code, v8 In-Reply-To: <20100903224047.GA8917@redhat.com> References: <20100903224047.GA8917@redhat.com> Message-ID: <20100905194101.GA31584@host1.dyn.jankratochvil.net> On Sat, 04 Sep 2010 00:40:47 +0200, Oleg Nesterov wrote: > - implement qXfer:siginfo:read > > - implement continue with signal. OK, thanks, just it was a bit premature to ask for it I see. I miss at least memory writes (also to put in breakpoints): (gdb) ptype done type = int (gdb) p done=1 $6 = 0 :-) Sending packet: $M7f00e6a378e0,1:cc#da...Packet received: - without much effect. Using some: killall -9 nc sigtest;gcc -o sigtest sigtest.c -Wall -g;nice -n20 ./sigtest&p=$!;nc -l 2000 <>/proc/ugdb >&0& ../gdb -nx -ex 'set architecture i386:x86-64' -ex 'set debug remote 0' -ex 'set debug solib 1' -ex 'set target-async on' -ex 'set non-stop on' -ex 'target extended-remote :2000' -ex 'file ./sigtest' -ex "attach $p" -ex 'info shared' Thanks, Jan From oleg at redhat.com Mon Sep 6 16:10:57 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 18:10:57 +0200 Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: <20100903203724.5CF26401B3@magilla.sf.frob.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> <20100826171355.GB20425@redhat.com> <20100902195053.2DDD140465@magilla.sf.frob.com> <20100902203333.GA24757@redhat.com> <20100903203724.5CF26401B3@magilla.sf.frob.com> Message-ID: <20100906161057.GA16102@redhat.com> On 09/03, Roland McGrath wrote: > > > > So, it is technically kosher enough to use UTRACE_INTERRUPT without > > > UTRACE_EVENT(QUIESCE) set, if you really know the situation and are sure > > > about all those caveats above. > > > > How? see below. > > I mentioned the examples. I misunderstood the "UTRACE_INTERRUPT without UTRACE_EVENT(QUIESCE)" above as if you mean it is possible to get UTRACE_SIGNAL_REPORT without QUIESCE. > > > But, it's only UTRACE_EVENT(QUIESCE) that > > > gives you any expectation of an "extra" callback for "no event" from either > > > UTRACE_REPORT or UTRACE_INTERRUPT. > > > > Yes, this is clear too. > > Apparently not. ;-) Perhaps ;) At least I certainly missed your point. > QUIESCE is the only event type for "no event". If you only asked for > signal events, then you only get a callback when there is an actual signal > event. If you want an extra callback before dequeuing any signal, then > that is what QUIESCE is for. OK. This means ugdb should set QUIESCE, just to ensure its ->report_signal() will be called. > > Once again, I am not asking to change utrace now, but could you explain > > what is wrong with the patch below? > > That gives an extra unrequested report_signal callback to every engine that > is only interested in some signal event. Consider a "crash-catcher" > engine. It would only track UTRACE_EVENT(SIGNAL_CORE) (and perhaps CLONE > for its bookkeeping). This engine never asked for a callback before each > and every attempt to dequeue any signal, I see your point (I hope). > which is what you would give it > with your change. No ;) My change was wrong. event == 0 in this case, and then later utrace_get_signal() checks if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) continue; OK, please forget. I must admit, this still looks a bit, well, unnatural to me. May be it makes sense to add _UTRACE_EVENT_SIGNAL_REPORT, _UTRACE_EVENT_SIGNAL_HANDLER, into utrace_events. Then ugdb could ask for UTRACE_SIGNAL_REPORT and avoid the unnecessary ->report_quiesce() calls. But at least I can see the logic now, thanks. Roland, could you also comment this patch? https://www.redhat.com/archives/utrace-devel/2010-August/msg00108.html Again, this looks like a bug to me, but I won't insist if it is not. Oleg. From oleg at redhat.com Mon Sep 6 18:18:08 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 20:18:08 +0200 Subject: gdbstub initial code, v8 In-Reply-To: <20100905194101.GA31584@host1.dyn.jankratochvil.net> References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> Message-ID: <20100906181808.GA22839@redhat.com> On 09/05, Jan Kratochvil wrote: > > On Sat, 04 Sep 2010 00:40:47 +0200, Oleg Nesterov wrote: > > - implement qXfer:siginfo:read > > > > - implement continue with signal. > > OK, thanks, just it was a bit premature to ask for it I see. I miss at least > memory writes Yes. This is simple. > (also to put in breakpoints): And this is not clear to me, I need your help ;) What should ugdb know about breakpoints? I played with the real gdbserver, and afaics gdb just changes the tracee's memory and inserts 0xcc (int 3). But gdb.info mentions "Z TYPE,ADDR,KIND" packets. So, what should ugdb do? Just implement memory write (M or X) and then report SIGTRAP like gdbserver does? Oleg. From oleg at redhat.com Mon Sep 6 18:23:59 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 20:23:59 +0200 Subject: gdbstub initial code, v8 && ptrace In-Reply-To: <20100903224047.GA8917@redhat.com> References: <20100903224047.GA8917@redhat.com> Message-ID: <20100906182359.GB22839@redhat.com> On 09/04, Oleg Nesterov wrote: > > - implement continue with signal. There is something wrong. I tried to debug the ptraced task via ugdb, and the result is not good. I am not surprised ugdb confuses ptrace, but I didn't expect that ptrace can break ugdb. I am still trying to understand what is wrong, it should be something simple but somehow I can't explain the problem so far... Oleg. From jan.kratochvil at redhat.com Mon Sep 6 18:31:42 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 6 Sep 2010 20:31:42 +0200 Subject: gdbstub initial code, v8 In-Reply-To: <20100906181808.GA22839@redhat.com> References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> <20100906181808.GA22839@redhat.com> Message-ID: <20100906183142.GA3256@host1.dyn.jankratochvil.net> On Mon, 06 Sep 2010 20:18:08 +0200, Oleg Nesterov wrote: > On 09/05, Jan Kratochvil wrote: > > On Sat, 04 Sep 2010 00:40:47 +0200, Oleg Nesterov wrote: > > memory writes > > Yes. This is simple. > > > (also to put in breakpoints): > > And this is not clear to me, I need your help ;) Sorry, I just meant that by implementing the memory writes breakpoints automatically start to work. > What should ugdb know about breakpoints? I played with the real > gdbserver, and afaics gdb just changes the tracee's memory and > inserts 0xcc (int 3). But gdb.info mentions "Z TYPE,ADDR,KIND" > packets. I believe it is described by: /* If GDB wanted this thread to single step, we always want to report the SIGTRAP, and let GDB handle it. Watchpoints should always be reported. So should signals we can't explain. A SIGTRAP we can't explain could be a GDB breakpoint --- we may or not support Z0 breakpoints. If we do, we're be able to handle GDB breakpoints on top of internal breakpoints, by handling the internal breakpoint and still reporting the event to GDB. If we don't, we're out of luck, GDB won't see the breakpoint hit. */ > So, what should ugdb do? Just implement memory write (M or X) > and then report SIGTRAP like gdbserver does? Therefore until you track some ugdb-specific software(*) breakpoints ugdb does not need to support Z0 IMO. I guess ugdb will never have to support these: thread-related(?) and tracepoint ones. (*) That is the memory-type one. There are also `hbreak' breakpoints via the CPU debug registers. Thanks, Jan From oleg at redhat.com Mon Sep 6 19:42:29 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 21:42:29 +0200 Subject: gdbstub initial code, v8 && ptrace In-Reply-To: <20100906182359.GB22839@redhat.com> References: <20100903224047.GA8917@redhat.com> <20100906182359.GB22839@redhat.com> Message-ID: <20100906194229.GA27405@redhat.com> On 09/06, Oleg Nesterov wrote: > > On 09/04, Oleg Nesterov wrote: > > > > - implement continue with signal. > > There is something wrong. I tried to debug the ptraced task via ugdb, > and the result is not good. I am not surprised ugdb confuses ptrace, > but I didn't expect that ptrace can break ugdb. > > I am still trying to understand what is wrong, it should be something > simple but somehow I can't explain the problem so far... OK, I am stupid. Indeed, say, "return UTRACE_STOP | UTRACE_SIGNAL_IGN" from under "case UTRACE_SIGNAL_REPORT" changes utrace_report->result, and confuses other tracers. Probably we can ignore ptrace, but this also means ugdb conflicts with itself and should be fixed. Oleg. From oleg at redhat.com Mon Sep 6 20:44:46 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 22:44:46 +0200 Subject: gdbstub initial code, v8 In-Reply-To: <20100906183142.GA3256@host1.dyn.jankratochvil.net> References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> <20100906181808.GA22839@redhat.com> <20100906183142.GA3256@host1.dyn.jankratochvil.net> Message-ID: <20100906204446.GA29925@redhat.com> On 09/06, Jan Kratochvil wrote: > > On Mon, 06 Sep 2010 20:18:08 +0200, Oleg Nesterov wrote: > > On 09/05, Jan Kratochvil wrote: > > > > > (also to put in breakpoints): > > > > And this is not clear to me, I need your help ;) > > Sorry, I just meant that by implementing the memory writes breakpoints > automatically start to work. > > > > What should ugdb know about breakpoints? I played with the real > > gdbserver, and afaics gdb just changes the tracee's memory and > > inserts 0xcc (int 3). But gdb.info mentions "Z TYPE,ADDR,KIND" > > packets. > > I believe it is described by: > /* If GDB wanted this thread to single step, we always want to > report the SIGTRAP, and let GDB handle it. Watchpoints should > always be reported. So should signals we can't explain. A > SIGTRAP we can't explain could be a GDB breakpoint --- we may or > not support Z0 breakpoints. If we do, we're be able to handle > GDB breakpoints on top of internal breakpoints, by handling the > internal breakpoint and still reporting the event to GDB. If we > don't, we're out of luck, GDB won't see the breakpoint hit. */ > > > > So, what should ugdb do? Just implement memory write (M or X) > > and then report SIGTRAP like gdbserver does? > > Therefore until you track some ugdb-specific software(*) breakpoints ugdb does > not need to support Z0 IMO. I guess ugdb will never have to support these: > thread-related(?) and tracepoint ones. Good! I thought ugdb should somehow handle this all "transparently" for gdb. I thought (I don't know why) that writing "int 3" from gdb side should be avoided in favour of some "better" method unknown to me. Thanks Jan. Oleg. From oleg at redhat.com Mon Sep 6 20:59:27 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 6 Sep 2010 22:59:27 +0200 Subject: gdbstub initial code, v8 && ptrace In-Reply-To: <20100906194229.GA27405@redhat.com> References: <20100903224047.GA8917@redhat.com> <20100906182359.GB22839@redhat.com> <20100906194229.GA27405@redhat.com> Message-ID: <20100906205927.GA30471@redhat.com> On 09/06, Oleg Nesterov wrote: > > OK, I am stupid. Indeed, say, "return UTRACE_STOP | UTRACE_SIGNAL_IGN" > from under "case UTRACE_SIGNAL_REPORT" changes utrace_report->result, > and confuses other tracers. > > Probably we can ignore ptrace, but this also means ugdb conflicts > with itself and should be fixed. Yes. I am a bit confused... OK, ugdb is wrong wrt multitracing. UTRACE_SIGNAL_REPORT case shouldn't return "UTRACE_STOP | UTRACE_SIGNAL_IGN", it should return "UTRACE_STOP | UTRACE_SIGNAL_REPORT" to keep report->result. But it needs to return UTRACE_SIGNAL_DELIVER? Probably we can check orig_ka != NULL and treat orig_ka == NULL as UTRACE_SIGNAL_REPORT. Hopefully this can't be confused with UTRACE_SIGNAL_HANDLER. Not sure about UTRACE_SIGNAL_HOLD, but this is very unlikely race. I need to re-read utrace_get_signal() with a fresh head. Oleg. From fche at redhat.com Tue Sep 7 02:59:37 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Mon, 06 Sep 2010 22:59:37 -0400 Subject: gdbstub initial code, v8 In-Reply-To: <20100906204446.GA29925@redhat.com> (Oleg Nesterov's message of "Mon, 6 Sep 2010 22:44:46 +0200") References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> <20100906181808.GA22839@redhat.com> <20100906183142.GA3256@host1.dyn.jankratochvil.net> <20100906204446.GA29925@redhat.com> Message-ID: Oleg Nesterov writes: > [...] >> Therefore until you track some ugdb-specific software(*) >> breakpoints ugdb does not need to support Z0 IMO. I guess ugdb >> will never have to support these: thread-related(?) and tracepoint >> ones. > Good! I thought ugdb should somehow handle this all "transparently" > for gdb. I thought (I don't know why) that writing "int 3" from gdb > side should be avoided in favour of some "better" method unknown to me. Please note that last year's gdbstub prototype used kernel uprobes as an optional gdb breakpoint implementation (i.e., a backend for the Z packets). When/if the lkml uprobes patches actually get merged, ugdb should also use them. - FChE From sales014 at 28581848.cn Tue Sep 7 05:42:16 2010 From: sales014 at 28581848.cn (kiko-america logistics) Date: Tue, 7 Sep 2010 13:42:16 +0800 Subject: shipping agent in shenzhen china! Message-ID: <201009070602.o87622FZ001322@mx2.redhat.com> Dear friend, This is Kiko , from Shipping Agent in China. I get your email from your website. I send email to you because i want to work with you. I think you have Fob cargo pls choose me we will reduce your cost. We America Shipping China, can provide competitive O/F from China to South &North America/Africa/Europe and so on. We also can Air freight. We also have competitive rate on other place container. So if you have cargo move , you must let me know , i will offer you a surprise rate . Enclosed our rate pls kindly find. Fob shenzhen--Doha Ocean Freight:USD1550/2450/2450 T/T:17days Fob shenzhen--los angeles Ocean Freight:USD1950/2450/2650 T/T:11days Fob shenzhen--New york/Miami/Savannah/Norfolk Ocean Freight:USD3300/4100/4400 T/T::24days/26days/28days Fob shenzhen--Ashdod/Beitut/Lattakia Ocean Freight:USD2050/3950/4050 T/T::23days/25days/25days Fob shenzhen--Abidjan/Tema/Apapa/Cotonou Ocean Freight:USD1950/3750/3850 Above rate valid till to Aug 31,2010 If this E-mail disturbs you and causes inconvenience, please inform us, and it will be stopped! Kind regards Oversea Dept :Kiko *************************************************************** America International Logistics(ShenZhen) Co.,Ltd Tel: 86-0755-82020113 Fax:86-0755-82020123 Moblie:13554866206 Skype:americalogistics888 QQ:385369704 E-mail:kiko at americalogi.com.cn Msn:kiko198263 at hotmail.com Http://www.americalogi.com.cn ADD;1708 BLOCK B, Business Building, South International Plaza, Fu Tian DISTRICT,Shen Zhen City, Guang Dong ,China -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: dolphins5.jpg Type: image/jpeg Size: 42634 bytes Desc: not available URL: From barbaradeans at gmail.com Tue Sep 7 20:38:17 2010 From: barbaradeans at gmail.com (Naquin thyratron) Date: 7 Sep 2010 21:38:17 +0100 Subject: Business/Medical/Consumer Mailing lists Message-ID: Until Friday Sep 10 buy any list below for just $199 each or 3 for $299: All lists are 100% optin and are 6 months or newer. ** HEALTHCARE LISTS ** - Physicians (34 specialties) - 788k records, 17k emails, 200k fax numbers - Chiropractors - 108,421 total records * 3,414 emails * 6,553 fax numbers - Alternative Medicine - 1,141,602 total records with 36,320 emails and 38.935 fax numbers - Dentists - 164k records, 45k emails, 77k fax numbers - Veterinarians - 78,986 total records with 1,438?emails and 1,050?fax numbers - Hospitals - 23,747 Hospital Administrators in over 7,145 Hospitals (full contact info no emails) - National Health Service Corp Clinics - 1,300 total records with emails for government run free clinics - Nursing Homes - 31,589 Senior Administrators, 11,288 Nursing Directors in over 14,706 Nursing Homes (full contact info no emails) - Pharmaceutical Companies - Email only list 47,000 emails of pharma company employees - Physical Therapists - 125,460 total records with 5,483 emails and 4,405 fax numbers - Oncology Doctors - 2,200 records all with emails - US Surgery Centers - 85k records and 14k emails - Massage Therapists - 76,701 records and 8,305 emails - Acupuncturists - 23,988 records 1,826 emails - Medical Equipment Suppliers - 167,425 total records with 6,940 emails and 5,812 fax numbers - Mental Health Counselors - 283,184 records 7,206 emails - Visiting Nurses & RN's - 91,386 total records with 2,788 emails and 2,390 fax numbers - Optometrists - 63,837 records 2,015 emails - Psychologists - 272,188 records and 9,874 emails ** BUSINESS AND FINANCE LISTS ** - Hotels - 34,815 total records * 1,642 emails - Real Estate Agents - 1 million records with emails - American Business Email List - 2 million emails various businesses - US New Business Database - 4.8 million records all with emails - Manufacturers Database - 1,057,119 records with 476,509 emails - Financial Planners Database - 148,857 records all with emails - Finance and Money Professionals Database - 116,568 records all with emails ** CONSUMER LISTS ** - American Consumer Database - 300,000 records all with emails. - Credit Inquiries Database - 1 million Full Data Records all with emails - American Homeowners - 1 million Full Data Records all with emails ** PROFESSIONALS LISTS ** - USA Lawyers Database - 269,787 records with 235,244 emails - Police and Sheriff Services - 42,987 records and 114 emails - Criminal Attorneys - 142,906 total records, 99,857 emails email me if you're interested: thinkresults at gmx.com Send email to offthelist at gmx.com to ensure no further communication ----------------------------------------- ** LEGAL DISCLAIMER ** FirstThis e-mail may contain confidential information of First Data Corporation. If you received this email in error please delete it and notify sender. Thank you. **** From oportunity at netcabo.pt Tue Sep 7 22:13:55 2010 From: oportunity at netcabo.pt (=?iso-8859-1?Q?Oportunity_Leil=F5es=2C_Lda?=) Date: Tue, 7 Sep 2010 22:13:55 +0000 (UTC) Subject: =?iso-8859-1?Q?GRANDE_LEIL=C3O_DE_VER=C3O_OPORTUNITY_-_7=2C8_e_9_de_Setembro=2C_mais_de_1000_Lotes_e_todos_a_partir_de_1_Euro_=21?= Message-ID: <20100907221355.5CE5DB06C6@173-203-101-198.static.cloud-ips.com> An HTML attachment was scrubbed... URL: From newsletter at lenjerie1.ro Mon Sep 6 11:54:14 2010 From: newsletter at lenjerie1.ro (Lenjerie intima 2010) Date: Mon, 06 Sep 2010 14:54:14 +0300 Subject: Lenjerie dama - calitate extra. Message-ID: An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1035_536_siva.jpg Type: image/jpeg Size: 38940 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1045_546_sartarella.jpg Type: image/jpeg Size: 33825 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1047_548_karioka.jpg Type: image/jpeg Size: 31476 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1052_553_fandango.jpg Type: image/jpeg Size: 29377 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1053_554_havanera.jpg Type: image/jpeg Size: 29658 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1055_556_maracato.jpg Type: image/jpeg Size: 29811 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1058_559_soleare.jpg Type: image/jpeg Size: 29712 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1061_562_quechua.jpg Type: image/jpeg Size: 27726 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1067_568_samba.jpg Type: image/jpeg Size: 30700 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1071_572_kiki.jpg Type: image/jpeg Size: 30932 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 1078_579_carimbo.jpg Type: image/jpeg Size: 31046 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2212_549_SETANTA.jpg Type: image/jpeg Size: 32654 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2676_483_sisi.jpg Type: image/jpeg Size: 49294 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2795_577_zorbared.jpg Type: image/jpeg Size: 29555 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2796_540_cocored.jpg Type: image/jpeg Size: 30392 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 952_461_mela.jpg Type: image/jpeg Size: 31917 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 963_473_fiki.jpg Type: image/jpeg Size: 30461 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 964_475_hera.jpg Type: image/jpeg Size: 30138 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 988_497_enya.jpg Type: image/jpeg Size: 31171 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 994_503_lilu.jpg Type: image/jpeg Size: 29798 bytes Desc: not available URL: From edra at mktimpacto.net.br Wed Sep 8 12:13:53 2010 From: edra at mktimpacto.net.br (EDRA) Date: Wed, 8 Sep 2010 12:13:53 GMT Subject: Nova tecnologia Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Sep 8 19:18:38 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 8 Sep 2010 21:18:38 +0200 Subject: gdbstub initial code, v9 Message-ID: <20100908191838.GA27120@redhat.com> Changes: - partly fix the multitracing problems. ugdb still can't work with ptrace, ptrace-utrace.c needs changes. But at least multiple udgb tracers can coexist, more or less. But of course they can confuse each other anyway, no matter what ugdb does. - implement memory writes ($M). - refactor memory reads to avoid the "Too late to report the error" case. But, Jan. Implementing the memory writes does not mean breakpoints automatically start to work! Yes, gdb writes cc, and yes the tracee reports SIGTRAP. But after that "continue" does nothing except "$c", and the tracee naturally gets SIGILL. I expected that, since ugdb doesn't even know the code was changed, gdb should write the original byte back before continue, but this doesn't happen. Tried to understand how this works with gdbserver, but failed so far. Will continue, but any hint is very much appreciated ;) Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (thread->t_siginfo) { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * Otherwise I do not know what to do, and anyway I don't * think gdb can try to cont a thread which was not reported * as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) return -EINVAL; /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; switch (*cmd++) { case 'C': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; lo = hex_to_bin(*cmd++); hi = hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Wed Sep 8 19:21:24 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 8 Sep 2010 21:21:24 +0200 Subject: gdbstub initial code, v8 In-Reply-To: References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> <20100906181808.GA22839@redhat.com> <20100906183142.GA3256@host1.dyn.jankratochvil.net> <20100906204446.GA29925@redhat.com> Message-ID: <20100908192124.GB27120@redhat.com> On 09/06, Frank Ch. Eigler wrote: > > Oleg Nesterov writes: > > > [...] > >> Therefore until you track some ugdb-specific software(*) > >> breakpoints ugdb does not need to support Z0 IMO. I guess ugdb > >> will never have to support these: thread-related(?) and tracepoint > >> ones. > > > Good! I thought ugdb should somehow handle this all "transparently" > > for gdb. I thought (I don't know why) that writing "int 3" from gdb > > side should be avoided in favour of some "better" method unknown to me. > > Please note that last year's gdbstub prototype used kernel uprobes as > an optional gdb breakpoint implementation (i.e., a backend for the Z > packets). When/if the lkml uprobes patches actually get merged, ugdb > should also use them. Yes, agreed. Oleg. From zhanghui8 at 188.com Thu Sep 9 01:40:31 2010 From: zhanghui8 at 188.com (=?gbk?B?1cW71A==?=) Date: Thu, 9 Sep 2010 09:40:31 +0800 (CST) Subject: =?gbk?B?0rvWsc/ry7WjrLWroaOho6GjoaOhow==?= Message-ID: <10c5790.9ad.12af426b42b.Coremail.zhanghui8@188.com> ?????? ????????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????????45???????????????????????????????????????????????????11????????????????????????45???????????????????????? ????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? ???????????????????? NO NO NO ??? ??????????? ????????????????????100%??? www.yingxiaomijue.com ???????????????? 1????3????248???????? 2?????????????????????? 3?7??????????????????? ? 4?????????????????????????????? 5????3???????????????14???1000????240000? ? 6?????????????????? ??????????? 7????????????????????????????????? 8?9????????? ?????????????????? ????????? ????????????????????????????????????????????????? ??????????????????????????????? ??????????????????????? ?????????????????????????????????? ???????????2???????????????????? ????????? ????13564693672 ???????????????????????? ????????? ????????????????????????? ps????????3?????????????????????48?????????????????????????????????????????????????????????????????? www.yingxiaomijue.com PPS???????????????????????????100??????????????????????50?????????????72?????????????????? ????13564693672 PPPS?????????????????????????????72??????????????????????? PPPPS???????????????????????????????????????????????????????????????????????????????1000?????? ??: www.yingxiaomijue.com ?????13564693672 QQ:694288858 ??VIP?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From zhanghui9 at 188.com Thu Sep 9 01:50:16 2010 From: zhanghui9 at 188.com (=?gbk?B?1cW71A==?=) Date: Thu, 9 Sep 2010 09:50:16 +0800 (CST) Subject: =?gbk?B?zbXX3y4uLi4uLi4utavH67K70qrN4sK2oaOho6GjoaM=?= Message-ID: <15175be.551b.12af42fa1d6.Coremail.zhanghui9@188.com> ?????? ????????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????????45???????????????????????????????????????????????????11????????????????????????45???????????????????????? ????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? ???????????????????? NO NO NO ??? ??????????? ????????????????????100%??? www.yingxiaomijue.com ???????????????? 1????3????248???????? 2?????????????????????? 3?7??????????????????? ? 4?????????????????????????????? 5????3???????????????14???1000????240000? ? 6?????????????????? ??????????? 7????????????????????????????????? 8?9????????? ?????????????????? ????????? ????????????????????????????????????????????????? ??????????????????????????????? ??????????????????????? ?????????????????????????????????? ???????????2???????????????????? ????????? ????13564693672 ???????????????????????? ????????? ????????????????????????? ps????????3?????????????????????48?????????????????????????????????????????????????????????????????? www.yingxiaomijue.com PPS???????????????????????????100??????????????????????50?????????????72?????????????????? ????13564693672 PPPS?????????????????????????????72??????????????????????? PPPPS???????????????????????????????????????????????????????????????????????????????1000?????? ??: www.yingxiaomijue.com ?????13564693672 QQ:694288858 ??VIP?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From zhanghui7 at 188.com Thu Sep 9 01:50:24 2010 From: zhanghui7 at 188.com (=?gbk?B?1cW71A==?=) Date: Thu, 9 Sep 2010 09:50:24 +0800 (CST) Subject: =?gbk?B?yMPE48uvvvW2vL/J0tQuLi4uLrS01OzUtNS0sru2z7XEytXI6y4uLi4uLi4uLg==?= Message-ID: <62fbb6.551e.12af42fc296.Coremail.zhanghui7@188.com> ?????? ????????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????????45???????????????????????????????????????????????????11????????????????????????45???????????????????????? ????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3?????????1????????????????????? ???????????????????? NO NO NO ??? ??????????? ????????????????????100%??? www.yingxiaomijue.com ???????????????? 1????3????248???????? 2?????????????????????? 3?7??????????????????? ? 4?????????????????????????????? 5????3???????????????14???1000????240000? ? 6?????????????????? ??????????? 7????????????????????????????????? 8?9????????? ?????????????????? ????????? ????????????????????????????????????????????????? ??????????????????????????????? ??????????????????????? ?????????????????????????????????? ???????????2???????????????????? ????????? ????13564693672 ???????????????????????? ????????? ????????????????????????? ps????????3?????????????????????48?????????????????????????????????????????????????????????????????? www.yingxiaomijue.com PPS???????????????????????????100??????????????????????50?????????????72?????????????????? ????13564693672 PPPS?????????????????????????????72??????????????????????? PPPPS???????????????????????????????????????????????????????????????????????????????1000?????? ??: www.yingxiaomijue.com ?????13564693672 QQ:694288858 ??VIP?? -------------- next part -------------- An HTML attachment was scrubbed... URL: From infomail at milenar.pt Thu Sep 9 05:09:23 2010 From: infomail at milenar.pt (=?iso-8859-1?Q?Jo=E3o_Almeida_-_Revista_S=E1bado_-_Milenar_Infomail?=) Date: 9 Sep 2010 05:09:23 +0000 Subject: =?iso-8859-1?Q?Informa=E7=E3o_privilegiada?= Message-ID: <20100909050923.18825.qmail@wpc0344.amenworld.com> An HTML attachment was scrubbed... URL: From heroinism at dcscomputer.com Thu Sep 9 05:51:26 2010 From: heroinism at dcscomputer.com (Summerour Marandi) Date: Thu, 09 Sep 2010 08:51:26 +0300 Subject: Your wife photos attached Message-ID: <4C88751C.3030407@dcscomputer.com> Your wife photos -------------- next part -------------- A non-text attachment was scrubbed... Name: hootch.zip Type: application/octet-stream Size: 12092 bytes Desc: not available URL: From certificadodigitalicpbrasil at gmail.com Thu Sep 9 06:24:22 2010 From: certificadodigitalicpbrasil at gmail.com (Certificado Digital ICP Brasil - CP MidiaCerta) Date: Thu, 9 Sep 2010 03:24:22 -0300 Subject: Certificado Digital ICP com desconto Message-ID: <54603504550242606731533@Geraldo-PC> PWB Certificado Digital ICP Brasil Parceria com Serasa S?o Paulo - SP - Brasil 31 de agosto de 2/010 Prezado/a Sr/a. ? com imenso prazer que fazemos este contato com o objetivo de atender as necessidades do mercado para Certificado Digital, informamos que acabamos de fechar uma parceira com a maior e mais completa Autoridade Certificadora do Brasil, para ofertar aos Empres?rios, P?blico em Geral, contabilistas e seus clientes Certificados Digitais a um pre?o promocional por tempo determinado.. Sr/a. segue em anexo os links para adquirirem os certificados a pre?os promocionais e efetue o pagamento em ate 10 dias ap?s emitir o certificado (o boleto ser? enviado para o endere?o do cliente). Para emitir os Certificados Adquiridos, favor verificar o ponto de atendimento mais pr?ximo, vejam postos no, Sescon SP, Serasa e Parceiros, mais pr?ximo da seu endere?o, clique aqui Caso tenha alguma d?vida ou queira mais informa??es, entre em contato. Obrigado pela sua prefer?ncia! Para comprar escolha os links abaixo e efetue o pedido com os pre?os promocionais Produto Validade Valor Promocional Clique aqui: e-CPF A3 em Token 3 anos De R$ 380,00 por R$ 342,00 Clique aqui: e-CPF A3 em Cart?o com Leitora 3 anos De R$ 380,00 por R$ 342,00 Clique aqui: e-CPF A3 em Cart?o 3 anos De R$ 220,00 por R$ 198,00 Clique aqui: e-CNPJ A3 em Token 3 anos De R$ 465,00 por R$ 418,50 Clique aqui: e-CNPJ A3 em Cart?o com Leitora 3 anos De R$ 465,00 por R$ 418,50 Clique aqui: e-CNPJ A3 em Cart?o 3 anos De R$ 300,00 por R$ 270,00 Clique aqui: e-CNPJ A3 sem M?dia 3 anos Super promo??o R$ 220,50 Clique aqui: Certificado Digital NF-e A1 1 ano De R$ 250,00 por R$ 225,00 Clique aqui: Certificado Digital NF-e A3 em Cart?o com Leitora 3 anos De R$ 550,00 por R$ 495,00 Clique aqui: Certificado Digital NF-e A3 em Cart?o 3 anos De R$ 450,00 por R$ 405,00 Clique aqui: Certificado Digital NF-e A3 sem M?dia 3 anos Super Promo??o R$ 297,00 Clique aqui: Certificado de Servidor NF-e 1 ano De R$ 1890,00 por R$ 1.701,00 Clique aqui: Certificado Digital PJ A3 NF-e para HSM 3 anos Super Promo??o R$ 1.035,00 Para saber sobre o uso do Certificado Digital Icp Brasil click aqui Atenciosamente, Vilella Diretor Comercial Repasse este email para seus amigos -------------- next part -------------- An HTML attachment was scrubbed... URL: From premiertraining at masteremarketing.com.br Wed Sep 8 22:03:26 2010 From: premiertraining at masteremarketing.com.br (Premier Training) Date: Wed, 08 Sep 2010 18:03:26 -0400 Subject: =?UTF-8?B?UmFkYXIgLSBIYWJpbGl0YcOnw6NvIHBhcmEgb3BlcmFyIGNvbSBpbXBvcnRhw6fDtWVzIGUgZXhwb3J0YcOnw7VlcyAtIDMwNjAtMjEwMA==?= Message-ID: An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Thu Sep 9 10:28:52 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Thu, 9 Sep 2010 12:28:52 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100908191838.GA27120@redhat.com> References: <20100908191838.GA27120@redhat.com> Message-ID: <20100909102851.GA30832@host1.dyn.jankratochvil.net> Hi Oleg, kernel-devel-2.6.34.6-54.fc13.x86_64 (real F13) says: ugdb.c:1988: error: implicit declaration of function ?hex_to_bin? Jan From fche at redhat.com Thu Sep 9 12:39:23 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 09 Sep 2010 08:39:23 -0400 Subject: gdbstub initial code, v9 In-Reply-To: <20100908191838.GA27120@redhat.com> (Oleg Nesterov's message of "Wed, 8 Sep 2010 21:18:38 +0200") References: <20100908191838.GA27120@redhat.com> Message-ID: Oleg Nesterov writes: > [...] > But, Jan. Implementing the memory writes does not mean breakpoints > automatically start to work! It approximately should though. > Yes, gdb writes cc, and yes the tracee reports SIGTRAP. But after > that "continue" does nothing except "$c", and the tracee naturally > gets SIGILL. I expected that, since ugdb doesn't even know the code > was changed, gdb should write the original byte back before continue, > but this doesn't happen. In normal all-stop mode, gdb does normally replace the old instruction, in order to single-step over it with the 's' packet. Perhaps you're testing some buggy non-stop aspect that only works with 'Z' breakpoint management packets? A fuller packet trace would help explain. - FChE From oleg at redhat.com Thu Sep 9 15:02:58 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 17:02:58 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909102851.GA30832@host1.dyn.jankratochvil.net> References: <20100908191838.GA27120@redhat.com> <20100909102851.GA30832@host1.dyn.jankratochvil.net> Message-ID: <20100909150258.GA20412@redhat.com> On 09/09, Jan Kratochvil wrote: > > Hi Oleg, > > kernel-devel-2.6.34.6-54.fc13.x86_64 (real F13) says: > > ugdb.c:1988: error: implicit declaration of function ?hex_to_bin? OOPS. It was added by 903788892ea0fc7fcaf7e8e5fac9a77379fc215b Please see the attachment with the copy-and-pastes hex_to_bin(). Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (thread->t_siginfo) { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * Otherwise I do not know what to do, and anyway I don't * think gdb can try to cont a thread which was not reported * as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) return -EINVAL; /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; switch (*cmd++) { case 'C': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } // XXX: hex_to_bin() after 90378889 commit #include static int cap_hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; lo = cap_hex_to_bin(*cmd++); hi = cap_hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From oleg at redhat.com Thu Sep 9 15:29:37 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 17:29:37 +0200 Subject: gdbstub initial code, v9 In-Reply-To: References: <20100908191838.GA27120@redhat.com> Message-ID: <20100909152937.GA21586@redhat.com> On 09/09, Frank Ch. Eigler wrote: > > Oleg Nesterov writes: > > > [...] > > But, Jan. Implementing the memory writes does not mean breakpoints > > automatically start to work! > > It approximately should though. > > > Yes, gdb writes cc, and yes the tracee reports SIGTRAP. But after > > that "continue" does nothing except "$c", and the tracee naturally > > gets SIGILL. I expected that, since ugdb doesn't even know the code > > was changed, gdb should write the original byte back before continue, > > but this doesn't happen. > > In normal all-stop mode, Currently ugdb only supports non-stop > gdb does normally replace the old > instruction, in order to single-step over it with the 's' packet. Yes, probably single-stepping is needed... I am still trying to understand how this works with gdbserver, but I see vCont:s packets. > Perhaps you're testing some buggy non-stop aspect that only works > with 'Z' breakpoint management packets? No. Just a trivial test-case which printfs in a loop. > A fuller packet trace > would help explain. Please see below. But the only important part is: $M4005ba,1:cc <------- set bp $c <------- resume of course, this can't work. Full trace: => qSupported:multiprocess+ <= PacketSize=400;QStartNoAckMode+;QNonStop+;multiprocess+;QPassS... => QStartNoAckMode <= OK => ! <= OK => Hgp0.0 <= E01 => QNonStop:1 <= OK => qfThreadInfo <= E01 => ? <= OK => qSymbol:: <= => vAttach;95b <= OK => qfThreadInfo <= mp95b.95b => qsThreadInfo <= l => Hgp95b.95b <= OK => vCont? <= vCont;t => vCont;t:p95b.-1 <= OK <= %Stop:T00thread:p95b.95b; => vStopped <= OK => g <= fcfdffffffffffff90ad5329ff7f0000ffffffffffffffff00000000000000... => m600880,8 <= 403c6d7d007f0000 => m7f007d6d3c48,8 <= 00106d7d007f0000 => m7f007d6d1000,28 <= 0000000000000000f6e04c7d007f0000e80760000000000080156d7d007f00... => m7f007d6d1580,28 <= 00f0ef29ff7f0000f6e04c7d007f000050f45f29ff7f000000c06c7d007f00... => m7f007d4ce0f4,4 <= 090a0069 => m7f007d6cc000,28 <= 0030167d007f0000781f6d7d007f0000400b4b7d007f0000e8346d7d007f00... => m7f007d6d1f78,4 <= 2f6c6962 => m7f007d6d1f7c,4 <= 2f6c6962 => m7f007d6d1f80,4 <= 632e736f => m7f007d6d1f84,4 <= 2e360000 => m7f007d6d34e8,28 <= 00704b7d007f00000002400000000000082e6d7d007f000000000000000000... => m400200,4 <= 2f6c6962 => m400204,4 <= 2f6c642d => m400208,4 <= 6c696e75 => m40020c,4 <= 782d7838 => m400210,4 <= 362d3634 => m400214,4 <= 2e736f2e => m400218,4 <= 32000000 => m7f007d6d3c40,4 <= 01000000 => m7f007d6d3c48,8 <= 00106d7d007f0000 => m7f007d6d3c50,8 <= c04e4c7d007f0000 => Z0,7f007d4c4ec0,1 <= => m7f007d4c4ec0,1 <= f3 => X7f007d4c4ec0,0: <= => M7f007d4c4ec0,1:cc <= OK => m600880,8 <= 403c6d7d007f0000 => m7f007d6d3c48,8 <= 00106d7d007f0000 => m7f007d6d1000,28 <= 0000000000000000f6e04c7d007f0000e80760000000000080156d7d007f00... => m7f007d6d1580,28 <= 00f0ef29ff7f0000f6e04c7d007f000050f45f29ff7f000000c06c7d007f00... => m7f007d4ce0f4,4 <= 090a0069 => m7f007d6cc000,28 <= 0030167d007f0000781f6d7d007f0000400b4b7d007f0000e8346d7d007f00... => m7f007d6d1f78,4 <= 2f6c6962 => m7f007d6d1f7c,4 <= 2f6c6962 => m7f007d6d1f80,4 <= 632e736f => m7f007d6d1f84,4 <= 2e360000 => m7f007d6d34e8,28 <= 00704b7d007f00000002400000000000082e6d7d007f000000000000000000... => m400200,4 <= 2f6c6962 => m400204,4 <= 2f6c642d => m400208,4 <= 6c696e75 => m40020c,4 <= 782d7838 => m400210,4 <= 362d3634 => m400214,4 <= 2e736f2e => m400218,4 <= 32000000 => m7f007d6d3c40,4 <= 01000000 => vCont;t:p95b.-1 <= OK => m7f007d201f40,1 <= 48 => m7f007d201f40,1 <= 48 => g <= fcfdffffffffffff90ad5329ff7f0000ffffffffffffffff00000000000000... => m7f007d201f40,1 <= 48 => m7f007d201f40,1 <= 48 => m40056c,12 <= 554889e5e8e3feffff89c6ba07000000bfdc => m40056c,1 <= 55 => m40056d,3 <= 4889e5 => m40056c,12 <= 554889e5e8e3feffff89c6ba07000000bfdc => m40056c,1 <= 55 => m40056d,3 <= 4889e5 => m4005ba,1 <= e8 => m4005ba,1 <= e8 (gdb) b BP.c:13 Breakpoint 1 at 0x4005ba: file BP.c, line 13. => M4005ba,1:cc <= OK gdb writes "int 3". (gdb) c Continuing. => QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c; <= OK => Hcp95b.95b <= OK => c <= OK <= %Stop:T05thread:p95b.95b; the tracee hits this bp and reports SIGTRAP => vStopped <= OK => g <= 00000000000000000006400000000000401f207d007f000000000000000000... => P10=ba05400000000000 <= => G00000000000000000006400000000000401f207d007f00000000000000000... <= => m4005ba,1 <= cc => m4005ba,1 <= cc => g <= 00000000000000000006400000000000401f207d007f000000000000000000... => m4005bb,1 <= 99 => m4005bb,1 <= 99 Breakpoint 1, main () at BP.c:13 13 printf("THREE %d %d\n\n", getpid(), __LINE__); (gdb) c Continuing. => c <= OK gdb just resumes the tracee, <= %Stop:T04thread:p95b.95b; and of course it gets SIGILL after "int 3" => vStopped <= OK => g <= 00000000000000000006400000000000401f207d007f000000000000000000... => m4005bc,1 <= fe => m4005bc,1 <= fe => g <= 00000000000000000006400000000000401f207d007f000000000000000000... => m4005bc,1 <= fe => m4005bc,1 <= fe => qTStatus <= T0 => M4005ba,1:e8 <= OK => M7f007d4c4ec0,1:f3 <= OK => D;95b <= OK => qTStatus <= T0 From oleg at redhat.com Thu Sep 9 15:50:47 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 17:50:47 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909152937.GA21586@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> Message-ID: <20100909155047.GA22403@redhat.com> On 09/09, Oleg Nesterov wrote: > > the tracee hits this bp and reports SIGTRAP > > => vStopped > <= OK > => g > <= 00000000000000000006400000000000401f207d007f000000000000000000... > => P10=ba05400000000000 > <= > => G00000000000000000006400000000000401f207d007f00000000000000000... > <= May be this can explain... Probably I need to implement G/P first, otherwise gdb can't change ip. Still, I'd appreciate if someone can explain me what gdb needs/expects to handle breakpoints before I start to read the sources. Oleg. From fche at redhat.com Thu Sep 9 16:07:00 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 9 Sep 2010 12:07:00 -0400 Subject: gdbstub initial code, v9 In-Reply-To: <20100909155047.GA22403@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> Message-ID: <20100909160700.GA26765@redhat.com> Hi - On Thu, Sep 09, 2010 at 05:50:47PM +0200, Oleg Nesterov wrote: > Probably I need to implement G/P first, otherwise gdb can't change ip. Perhaps. > Still, I'd appreciate if someone can explain me what gdb needs/expects > to handle breakpoints before I start to read the sources. It'd be simpler if the normal all-stop mode was what you first focused on. That mode works fine with Z/z and with M/m based breakpoint insertion/removal and c/s continue/singlestep. (This stuff was all working in the earlier gdbstub code.) Re. non-stop mode, see http://www.codesourcery.com/publications/non_stop_multi_threaded_debugging_in_gdb.pdf - FChE From jan.kratochvil at redhat.com Thu Sep 9 16:04:23 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Thu, 9 Sep 2010 18:04:23 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909155047.GA22403@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> Message-ID: <20100909160423.GA9768@host1.dyn.jankratochvil.net> On Thu, 09 Sep 2010 17:50:47 +0200, Oleg Nesterov wrote: > Probably I need to implement G/P first, otherwise gdb can't change ip. > > Still, I'd appreciate if someone can explain me what gdb needs/expects > to handle breakpoints before I start to read the sources. Yes, GDB tries to set PC to PC-1 to skip back after the hit of 0xCC. As it fails to fix-up PC then PC is wrong and trap_expected is then 0 (it should be 1) and everything fails. BTW ugdb needs one simple fix. :-) (gdb) p/x done=0x5a $1 = 0xa5 Thanks, Jan From oleg at redhat.com Thu Sep 9 16:30:31 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 18:30:31 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909160423.GA9768@host1.dyn.jankratochvil.net> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> Message-ID: <20100909163031.GA23799@redhat.com> On 09/09, Jan Kratochvil wrote: > > On Thu, 09 Sep 2010 17:50:47 +0200, Oleg Nesterov wrote: > > Probably I need to implement G/P first, otherwise gdb can't change ip. > > > > Still, I'd appreciate if someone can explain me what gdb needs/expects > > to handle breakpoints before I start to read the sources. > > Yes, GDB tries to set PC to PC-1 to skip back after the hit of 0xCC. > As it fails to fix-up PC then PC is wrong and trap_expected is then 0 (it > should be 1) and everything fails. OK. I'll implement G or P, then we will see. But probably not right now, I have to switch to bug-report I have. > BTW ugdb needs one simple fix. :-) > (gdb) p/x done=0x5a > $1 = 0xa5 OOPS! indeed, unhex() confuses lo and hi. I am attaching ugdb.c with the trivial fix. Thanks! Cough... could you tell me how can I change the variable "done" without printing it? Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, 0); ugdb_control(thread, UTRACE_RESUME); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (thread->t_siginfo) { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * Otherwise I do not know what to do, and anyway I don't * think gdb can try to cont a thread which was not reported * as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) return -EINVAL; /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; switch (*cmd++) { case 'C': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } // XXX: hex_to_bin() after 90378889 commit #include static int cap_hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; hi = cap_hex_to_bin(*cmd++); lo = cap_hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From jan.kratochvil at redhat.com Thu Sep 9 16:36:35 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Thu, 9 Sep 2010 18:36:35 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909163031.GA23799@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> Message-ID: <20100909163635.GA12356@host1.dyn.jankratochvil.net> On Thu, 09 Sep 2010 18:30:31 +0200, Oleg Nesterov wrote: > OOPS! indeed, unhex() confuses lo and hi. It works for 0xcc, though. > Cough... could you tell me how can I change the variable "done" > without printing it? (gdb) help set variable Evaluate expression EXP and assign result to variable VAR, using assignment syntax appropriate for the current language (VAR = EXP or VAR := EXP for example). VAR may be a debugger "convenience" variable (names starting with $), a register (a few standard names starting with $), or an actual variable in the program being debugged. EXP is any valid expression. This may usually be abbreviated to simply "set". Regards, Jan From oleg at redhat.com Thu Sep 9 16:34:00 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 18:34:00 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909160700.GA26765@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160700.GA26765@redhat.com> Message-ID: <20100909163400.GB23799@redhat.com> On 09/09, Frank Ch. Eigler wrote: > Hi - > > On Thu, Sep 09, 2010 at 05:50:47PM +0200, Oleg Nesterov wrote: > > > Probably I need to implement G/P first, otherwise gdb can't change ip. > > Perhaps. > > > Still, I'd appreciate if someone can explain me what gdb needs/expects > > to handle breakpoints before I start to read the sources. > > It'd be simpler if the normal all-stop mode was what you first focused > on. That mode works fine with Z/z and with M/m based breakpoint > insertion/removal and c/s continue/singlestep. (This stuff was all > working in the earlier gdbstub code.) > > Re. non-stop mode, see > http://www.codesourcery.com/publications/non_stop_multi_threaded_debugging_in_gdb.pdf Thanks a lot, downloaded. Oleg. From oleg at redhat.com Thu Sep 9 16:45:00 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 18:45:00 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909163635.GA12356@host1.dyn.jankratochvil.net> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> Message-ID: <20100909164500.GA25164@redhat.com> On 09/09, Jan Kratochvil wrote: > > > Cough... could you tell me how can I change the variable "done" > > without printing it? > > (gdb) help set variable > Evaluate expression EXP and assign result to variable VAR, using assignment > syntax appropriate for the current language (VAR = EXP or VAR := EXP for > example). VAR may be a debugger "convenience" variable (names starting > with $), a register (a few standard names starting with $), or an actual > variable in the program being debugged. EXP is any valid expression. > This may usually be abbreviated to simply "set". Thanks... but I tried this when I tested the fix. (gdb) p/x var $1 = 0x1234 (gdb) set var Argument required (expression to compute). (gdb) set var 0 (gdb) p/x var $2 = 0x1234 strange ;) Oleg. From oleg at redhat.com Thu Sep 9 16:47:13 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 9 Sep 2010 18:47:13 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100909164500.GA25164@redhat.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> Message-ID: <20100909164713.GB25164@redhat.com> On 09/09, Oleg Nesterov wrote: > > Thanks... but I tried this when I tested the fix. > > (gdb) p/x var > $1 = 0x1234 > (gdb) set var > Argument required (expression to compute). > (gdb) set var 0 > (gdb) p/x var > $2 = 0x1234 > > strange ;) Aah. (gdb) set variable var=0x4321 (gdb) p/x var $7 = 0x4321 Thanks ;) Oleg. From tromey at redhat.com Thu Sep 9 16:51:27 2010 From: tromey at redhat.com (Tom Tromey) Date: Thu, 09 Sep 2010 10:51:27 -0600 Subject: gdbstub initial code, v9 In-Reply-To: <20100909164500.GA25164@redhat.com> (Oleg Nesterov's message of "Thu, 9 Sep 2010 18:45:00 +0200") References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> Message-ID: >>>>> "Oleg" == Oleg Nesterov writes: Oleg> (gdb) set var 0 You need: set variable var = 0 The "variable" can be abbreviated. FWIW, "print", "set variable", and "call" are basically aliases. "print" just happens to print the result of the expression. Tom From roland at redhat.com Fri Sep 10 10:01:51 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 03:01:51 -0700 (PDT) Subject: gdbstub initial code, v8 In-Reply-To: Frank Ch. Eigler's message of Monday, 6 September 2010 22:59:37 -0400 References: <20100903224047.GA8917@redhat.com> <20100905194101.GA31584@host1.dyn.jankratochvil.net> <20100906181808.GA22839@redhat.com> <20100906183142.GA3256@host1.dyn.jankratochvil.net> <20100906204446.GA29925@redhat.com> Message-ID: <20100910100151.8D7E7405D5@magilla.sf.frob.com> > Please note that last year's gdbstub prototype used kernel uprobes as > an optional gdb breakpoint implementation (i.e., a backend for the Z > packets). When/if the lkml uprobes patches actually get merged, ugdb > should also use them. That's something for later, and it's not quite so simple. If a utrace engine ever uses uprobes, it probably would need to use the utrace-based version of uprobes. If something different goes in upstream, it remains to be seen how it would interact with utrace, and there would be specific work required for that. There are many more issues about that too. At any rate, this is all a distraction at the moment, and Oleg doesn't need any more of those! Thanks, Roland From roland at redhat.com Fri Sep 10 10:09:48 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 03:09:48 -0700 (PDT) Subject: gdbstub initial code, v8 && ptrace In-Reply-To: Oleg Nesterov's message of Monday, 6 September 2010 22:59:27 +0200 <20100906205927.GA30471@redhat.com> References: <20100903224047.GA8917@redhat.com> <20100906182359.GB22839@redhat.com> <20100906194229.GA27405@redhat.com> <20100906205927.GA30471@redhat.com> Message-ID: <20100910100948.C0254405D5@magilla.sf.frob.com> > I am a bit confused... OK, ugdb is wrong wrt multitracing. > UTRACE_SIGNAL_REPORT case shouldn't return "UTRACE_STOP | UTRACE_SIGNAL_IGN", > it should return "UTRACE_STOP | UTRACE_SIGNAL_REPORT" to keep report->result. No, UTRACE_SIGNAL_REPORT is not meant for a return value. Its only use is in the incoming argument to tell you that a given report_signal call is standing in for a report_quiesce(0) call. > But it needs to return UTRACE_SIGNAL_DELIVER? That's what you return when you want the signal delivered. When you are stopping the tracee to decide about the signal, that's not what you want. UTRACE_STOP | UTRACE_SIGNAL_IGN is correct to not deliver the signal right now, and stop instead. If you want to deliver the signal later, then you'll resume with UTRACE_INTERRUPT to ensure you get back to report_signal and that can fill in the details and return UTRACE_SIGNAL_DELIVER. > Probably we can check orig_ka != NULL and treat orig_ka == NULL as > UTRACE_SIGNAL_REPORT. Hopefully this can't be confused with > UTRACE_SIGNAL_HANDLER. I'm not really sure what you mean here. > Not sure about UTRACE_SIGNAL_HOLD, but this is very unlikely race. You probably don't want to use that, but I'm not entirely sure. ptrace doesn't use it, and the signal interception model is pretty much the same. Thanks, Roland From roland at redhat.com Fri Sep 10 10:12:42 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 03:12:42 -0700 (PDT) Subject: gdbstub initial code, v9 In-Reply-To: Tom Tromey's message of Thursday, 9 September 2010 10:51:27 -0600 References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> Message-ID: <20100910101242.F0B83405D5@magilla.sf.frob.com> > >>>>> "Oleg" == Oleg Nesterov writes: > > Oleg> (gdb) set var 0 > > You need: set variable var = 0 > The "variable" can be abbreviated. I've always just used: (gdb) set var=0 Thanks, Roland From roland at redhat.com Fri Sep 10 10:14:52 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 03:14:52 -0700 (PDT) Subject: gdbstub initial code, v7 In-Reply-To: Oleg Nesterov's message of Saturday, 4 September 2010 01:09:57 +0200 <20100903230957.GC8917@redhat.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903230957.GC8917@redhat.com> Message-ID: <20100910101452.39015405D5@magilla.sf.frob.com> > But I meant another case, when the stopped tracee doesn't have siginfo. > Currently ugdb just sends this signal to tracee, and then it will be > reported to gdb. Not sure if this is right or not, I can change this. > (or perhap this doesn't matter, I dunno). What do you mean by "doesn't have siginfo"? You mean non-signal stops? What non-signal stops does ugdb report? Thanks, Roland From roland at redhat.com Fri Sep 10 10:26:05 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 03:26:05 -0700 (PDT) Subject: [PATCH 0/3] UTRACE_DETACH fixes In-Reply-To: Oleg Nesterov's message of Monday, 6 September 2010 18:10:57 +0200 <20100906161057.GA16102@redhat.com> References: <20100816093924.GA24425@redhat.com> <20100816145149.GA7801@redhat.com> <20100816150939.GA8842@redhat.com> <20100817005151.882C74007E@magilla.sf.frob.com> <20100817142751.GA9649@redhat.com> <20100819212229.BC4F940080@magilla.sf.frob.com> <20100826171355.GB20425@redhat.com> <20100902195053.2DDD140465@magilla.sf.frob.com> <20100902203333.GA24757@redhat.com> <20100903203724.5CF26401B3@magilla.sf.frob.com> <20100906161057.GA16102@redhat.com> Message-ID: <20100910102605.33468405D5@magilla.sf.frob.com> > I misunderstood the "UTRACE_INTERRUPT without UTRACE_EVENT(QUIESCE)" above > as if you mean it is possible to get UTRACE_SIGNAL_REPORT without QUIESCE. No, I meant the opposite: since you won't get UTRACE_SIGNAL_REPORT without UTRACE_EVENT(QUIESCE), it might seem that UTRACE_INTERRUPT should not be permitted, as UTRACE_REPORT is not. But because that is not it's *only* effect, we don't do permit it even though you won't get UTRACE_SIGNAL_REPORT. > OK. This means ugdb should set QUIESCE, just to ensure its ->report_signal() > will be called. If you ever want UTRACE_SIGNAL_REPORT calls, yes. > OK, please forget. I must admit, this still looks a bit, well, unnatural > to me. May be it makes sense to add > > _UTRACE_EVENT_SIGNAL_REPORT, > _UTRACE_EVENT_SIGNAL_HANDLER, > > into utrace_events. Then ugdb could ask for UTRACE_SIGNAL_REPORT and > avoid the unnecessary ->report_quiesce() calls. If anything, I think UTRACE_EVENT(RESUME) would make sense, perhaps with a separate ->report_resume callback. That would request only the cases that now get report_quiesce(0). But, it really does not cost much to have if (event) return UTRACE_RESUME; or similar in your report_quiesce callback. It's beyond refinement of the utrace API (that we're not doing now), it's just micro-optimization. > Roland, could you also comment this patch? > > https://www.redhat.com/archives/utrace-devel/2010-August/msg00108.html > > Again, this looks like a bug to me, but I won't insist if it is not. Sorry, that is still on my queue. I haven't forgotten it. I just haven't gotten to reviewing it yet because of other work and it needing a lot of hard thinking. Thanks, Roland From qacy at bxgz.com Fri Sep 10 17:06:07 2010 From: qacy at bxgz.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 11 Sep 2010 01:06:07 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVszve149a00NDBpg==?= Message-ID: <201009101706.o8AH5vNj005761@mx1.redhat.com> utrace-devel????? ?????2010?09?27-28? ?? ?????2010?09?29-30??? ????2680?????????????????????????????? ??????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ?????????????????????????????200????????????????? ??3700????????500?????1000??????2000???????5000?????????? ??????????????????????????????? ??????????????????????????????????????????????? ????????????????1030??????????????5????????????90%? ??????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????? ------------------------------------------------------------------------------------------- ????? 1.????????????????????????? 2.???????????????????? 3.????????????????????????????????? ---------------------------------------------------------------------------------------------- ????? 1.????????????????????????????????????? 2.??????????????????????????????????????? ------------------------------------------------------------------------------------ ????? ????????????? ??? ???????????????? ???????????? ???22??? ??????? ???????????? ?????????? ????????????????? ??????????????? ????????? ?????????????? ????????????? ????????????? ???? ??????? ???????? ????????????? ?????????? ?????????? ?????????? ????????????? ?????????????? ????????? ????????? ????????? ???????????????? ????????????? ?????????????? 80/20?? ???????? ?????? ????? ????????????? ??????????????? ?????????? ?????????????? ?????????? ???????????? ???? ???? ???? ?????????????????? ??????????? ???????????? ????????????? ????????? ??????????? ????????? ???? ???? ???? ????? ???????? ??????? ??????????? ???? ???? ???? ???16??? ???24??? ??????? ????????????? ????????????????? ?????????????? ???GE?????????? ????????????? ??????????? ????????? ????????? ????????? ????????? ????????????? ???????????? ???????????? ???????????? ?????????? ??????? ???? ???? ????????? ????????????????? ?????????????? ????????????? ????????????? ????????????? ????????????? ???????????????? ??????&??????? ??????????????? ??????? ??????? ??????? ??????? ??????????? ????????????? ????????????????? ?????????? ??????????????? ???????????? ????????????? ???????????? ?????????????????? ????????????????? ???????? ???? ???? ???? ???? ???? ????????4P?? ?????????? ??????????? ?????????? ??????????????? ??????????? ??????? -------------------------------------------------------------------------- ????????????GEC??????????????PTT???????????? ???????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????04?????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ???????????????????????????HR??????????????? ???????? ??????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????TCL???????? ????????? -------------------------------------------------------------------- ????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Fri Sep 10 18:11:00 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 10 Sep 2010 20:11:00 +0200 Subject: gdbstub initial code, v9 In-Reply-To: <20100910101242.F0B83405D5@magilla.sf.frob.com> References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> <20100910101242.F0B83405D5@magilla.sf.frob.com> Message-ID: <20100910181100.GA27699@redhat.com> On 09/10, Roland McGrath wrote: > > > >>>>> "Oleg" == Oleg Nesterov writes: > > > > Oleg> (gdb) set var 0 > > > > You need: set variable var = 0 > > The "variable" can be abbreviated. > > I've always just used: > > (gdb) set var=0 No, I tried this too, doesn't work. (gdb) set var=0 A syntax error in expression, near `=0'. But, it turns out I choosed a bad name for the variable when I tested the fix in unxex(). (gdb) set xxx=0 This works. (gdb) set var var=0 This works too. I guess, when gdb sees "set var" it expects the full "set variable ..." command. Oleg. From oleg at redhat.com Fri Sep 10 18:29:03 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 10 Sep 2010 20:29:03 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100910101452.39015405D5@magilla.sf.frob.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903230957.GC8917@redhat.com> <20100910101452.39015405D5@magilla.sf.frob.com> Message-ID: <20100910182903.GB27699@redhat.com> On 09/10, Roland McGrath wrote: > > > But I meant another case, when the stopped tracee doesn't have siginfo. > > Currently ugdb just sends this signal to tracee, and then it will be > > reported to gdb. Not sure if this is right or not, I can change this. > > (or perhap this doesn't matter, I dunno). > > What do you mean by "doesn't have siginfo"? You mean non-signal stops? Yes. > What non-signal stops does ugdb report? (gdb) interrupt ugdb sets "please stop" flag and does utrace_control(INTERRUPT). However, in unlikely case the tracee can stop before ->report_signal() reporting loop (especially in multitracing case). Or it can be already stopped (note: this needs a separate discussion, currently ugdb intentionally doesn't handle this case). And. With the current implementation, even if the tracee stops after ugdb_report_signal() was called, it doesn't setup ->t_siginfo. IOW. If the tracee actually recieves a signal, then - qXfer:siginfo:read works - "signal SIG" works as expected (delivered to tracee) Otherwise - qXfer:siginfo:read reports E01 - "signal XX" means TXX report. Once again, this can be changed (fixed?), but I am not sure this should be changed. Oleg. From roland at redhat.com Fri Sep 10 19:05:47 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 10 Sep 2010 12:05:47 -0700 (PDT) Subject: gdbstub initial code, v7 In-Reply-To: Oleg Nesterov's message of Friday, 10 September 2010 20:29:03 +0200 <20100910182903.GB27699@redhat.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903230957.GC8917@redhat.com> <20100910101452.39015405D5@magilla.sf.frob.com> <20100910182903.GB27699@redhat.com> Message-ID: <20100910190547.85CBD405D5@magilla.sf.frob.com> > ugdb sets "please stop" flag and does utrace_control(INTERRUPT). However, > in unlikely case the tracee can stop before ->report_signal() reporting I don't think this is the right thing to do. When the intent is explicitly to interrupt, there is no reason to stop before the interruption is complete, i.e. report_signal. If you only stop there, then you can always process a signal injection with complete flexibility. The gdb model and the remote protocol doesn't currently have any concept of requesting a stop that is not an interruption. Thanks, Roland From oleg at redhat.com Fri Sep 10 19:07:25 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 10 Sep 2010 21:07:25 +0200 Subject: gdbstub initial code, v8 && ptrace In-Reply-To: <20100910100948.C0254405D5@magilla.sf.frob.com> References: <20100903224047.GA8917@redhat.com> <20100906182359.GB22839@redhat.com> <20100906194229.GA27405@redhat.com> <20100906205927.GA30471@redhat.com> <20100910100948.C0254405D5@magilla.sf.frob.com> Message-ID: <20100910190725.GC27699@redhat.com> On 09/10, Roland McGrath wrote: > > > I am a bit confused... OK, ugdb is wrong wrt multitracing. > > UTRACE_SIGNAL_REPORT case shouldn't return "UTRACE_STOP | UTRACE_SIGNAL_IGN", > > it should return "UTRACE_STOP | UTRACE_SIGNAL_REPORT" to keep report->result. > > No, UTRACE_SIGNAL_REPORT is not meant for a return value. Its only use is > in the incoming argument to tell you that a given report_signal call is > standing in for a report_quiesce(0) call. Yes, that is why initially ugdb returned " | UTRACE_SIGNAL_IGN". But you misunerstood my concerns (or me your reply ;) But. Suppose we have to attached engines. The first engine gets UTRACE_SIGNAL_REPORT and returns "UTRACE_STOP | UTRACE_SIGNAL_IGN". Or, > > But it needs to return UTRACE_SIGNAL_DELIVER? > > That's what you return when you want the signal delivered. or yes, it returns UTRACE_SIGNAL_DELIVER after gdb does "signal XX". Now. The second engine gets UTRACE_SIGNAL_DELIVER or UTRACE_SIGNAL_IGN, not UTRACE_SIGNAL_REPORT. That is why ugdb_signal_report(UTRACE_SIGNAL_REPORT) tries to return UTRACE_STOP | utrace_signal_action(action) to not change report->result (passed to the next tracee) inside the reporting loop. The worst case is UTRACE_SIGNAL_HANDLER. Single-stepping should know about this case. This means that any engine should always return UTRACE_resume_action | UTRACE_SIGNAL_HANDLER. Unless we are going to change utrace_get_signal(). > > Probably we can check orig_ka != NULL and treat orig_ka == NULL as > > UTRACE_SIGNAL_REPORT. Hopefully this can't be confused with > > UTRACE_SIGNAL_HANDLER. > > I'm not really sure what you mean here. If ->report_signal(orig_ka) was calles with orig_ka == NULL, then, whatever utrace_signal_action(action) we see, originally it was either UTRACE_SIGNAL_HANDLER or UTRACE_SIGNAL_REPORT but another engine returned, say, UTRACE_SIGNAL_DELIVER/UTRACE_SIGNAL_IGN to deliver/stop. > > Not sure about UTRACE_SIGNAL_HOLD, but this is very unlikely race. > > You probably don't want to use that, but I'm not entirely sure. ptrace > doesn't use it, and the signal interception model is pretty much the same. Yes, agreed. But there is one corner case. Until we generalize utrace_stop()->ptrace_notify_stop() hook, the tracee can be reported as stopped to gdb, but before it actually stops it can recieve a signal. The remote protocol doesn't allow to send TSIG after we alreay sent T00 (at least this actually confuses gdb), and we can't just stop, the tracee should report this signal to debugger. So, currently ugdb stops but uses UTRACE_SIGNAL_HOLD to report this signal later. Oleg. From oleg at redhat.com Fri Sep 10 19:20:01 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 10 Sep 2010 21:20:01 +0200 Subject: gdbstub initial code, v7 In-Reply-To: <20100910190547.85CBD405D5@magilla.sf.frob.com> References: <20100830185850.GA1132@redhat.com> <20100830192040.GA15431@host1.dyn.jankratochvil.net> <20100831072048.GA26362@host1.dyn.jankratochvil.net> <20100902200632.GA23692@redhat.com> <20100903064008.GA16249@host1.dyn.jankratochvil.net> <20100903230957.GC8917@redhat.com> <20100910101452.39015405D5@magilla.sf.frob.com> <20100910182903.GB27699@redhat.com> <20100910190547.85CBD405D5@magilla.sf.frob.com> Message-ID: <20100910192001.GA30490@redhat.com> On 09/10, Roland McGrath wrote: > > > ugdb sets "please stop" flag and does utrace_control(INTERRUPT). However, > > in unlikely case the tracee can stop before ->report_signal() reporting > > I don't think this is the right thing to do. When the intent is explicitly > to interrupt, there is no reason to stop before the interruption is > complete, i.e. report_signal. This means that ugdb_report_quiesce() should never return UTRACE_STOP, and that is all. But what about multitracing? Suppose that "(gdb) interrupt" happens just before, say, do_report_syscall_entry() and another engine wants to stop. If ugdb_report_quiesce() doesn't return UTRACE_STOP, then gdb will wait until another debugger resumes the tracee. What do you think? > If you only stop there, then you can always > process a signal injection with complete flexibility. Yes, sure (again, currently ugdb does not injection a signal even if the tracee was stopped in report_signal, but of course we can change this). Oleg. From tromey at redhat.com Fri Sep 10 19:42:54 2010 From: tromey at redhat.com (Tom Tromey) Date: Fri, 10 Sep 2010 13:42:54 -0600 Subject: gdbstub initial code, v9 In-Reply-To: <20100910181100.GA27699@redhat.com> (Oleg Nesterov's message of "Fri, 10 Sep 2010 20:11:00 +0200") References: <20100908191838.GA27120@redhat.com> <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> <20100910101242.F0B83405D5@magilla.sf.frob.com> <20100910181100.GA27699@redhat.com> Message-ID: >>>>> "Oleg" == Oleg Nesterov writes: >> I've always just used: >> (gdb) set var=0 Oleg> No, I tried this too, doesn't work. Oleg> (gdb) set var=0 Oleg> A syntax error in expression, near `=0'. Yeah, it is ambiguous if the actual variable name conflicts with any gdb "set" subcommand. I typically just use call or print. Tom From oleg at redhat.com Fri Sep 10 19:46:02 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 10 Sep 2010 21:46:02 +0200 Subject: gdbstub initial code, v9 In-Reply-To: References: <20100909152937.GA21586@redhat.com> <20100909155047.GA22403@redhat.com> <20100909160423.GA9768@host1.dyn.jankratochvil.net> <20100909163031.GA23799@redhat.com> <20100909163635.GA12356@host1.dyn.jankratochvil.net> <20100909164500.GA25164@redhat.com> <20100910101242.F0B83405D5@magilla.sf.frob.com> <20100910181100.GA27699@redhat.com> Message-ID: <20100910194602.GA32040@redhat.com> On 09/10, Tom Tromey wrote: > > >>>>> "Oleg" == Oleg Nesterov writes: > > >> I've always just used: > >> (gdb) set var=0 > > Oleg> No, I tried this too, doesn't work. > Oleg> (gdb) set var=0 > Oleg> A syntax error in expression, near `=0'. > > Yeah, it is ambiguous if the actual variable name conflicts with any gdb > "set" subcommand. Ah, good to know. gdb has a lot of them ;) Oleg. From oleg at redhat.com Fri Sep 10 22:00:07 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 11 Sep 2010 00:00:07 +0200 Subject: ugdb && breakpoints In-Reply-To: References: <20100908191838.GA27120@redhat.com> Message-ID: <20100910220007.GA6587@redhat.com> On 09/09, Frank Ch. Eigler wrote: > > Oleg Nesterov writes: > > > [...] > > But, Jan. Implementing the memory writes does not mean breakpoints > > automatically start to work! > > It approximately should though. No. Frank, I guess I did a mistake, I should have read the pdf you sent me first. I'll read it anyway later, but I think that I already understand how this work. gdb replaces the original insn with "int 3". the tracee reports SIGTRAP. Now, to continue the tracee, gdb does not restore the original instruction. Instead, it - writes this insn into _start code - changes regs->ip to point to this insn - does single-step to execute this insn - changes regs->ip again So. Let's forget about breakpoints temporary. ugdb needs the single stepping first. Damn. I spent much more time than I'd wish trying to understand this. I misunderstood the "target byte order" part in the documentation of P packet. Oleg. From tromey at redhat.com Fri Sep 10 22:12:12 2010 From: tromey at redhat.com (Tom Tromey) Date: Fri, 10 Sep 2010 16:12:12 -0600 Subject: ugdb && breakpoints In-Reply-To: <20100910220007.GA6587@redhat.com> (Oleg Nesterov's message of "Sat, 11 Sep 2010 00:00:07 +0200") References: <20100908191838.GA27120@redhat.com> <20100910220007.GA6587@redhat.com> Message-ID: Oleg> Now, to continue the tracee, gdb does not restore the Oleg> original instruction. Instead, it Oleg> - writes this insn into _start code Oleg> - changes regs->ip to point to this insn Oleg> - does single-step to execute this insn Oleg> - changes regs->ip again This is what is done for non-stop. I believe it is called "displaced stepping" in gdb. I think eventually we would like it if uprobes did this work, instead of gdb doing it. Presumably that would yield better performance. E.g., if we have a thread-specific breakpoint, then other threads hitting that breakpoint could simply do the displaced stepping via uprobes, and not report a breakpoint hit to gdb at all. For all-stop, breakpoints are handled differently, though I don't remember how offhand. Tom From amgo at cghy.com Sat Sep 11 08:33:29 2010 From: amgo at cghy.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sat, 11 Sep 2010 08:33:29 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsyOe6zrj8usO8pMD4z/rK276r06I=?= Message-ID: <201009110832.o8B8Wsrj006814@mx1.redhat.com> utrace-devel????????2?????????? ???????????????????????????????????????????????????????????????????????????? ??????????2010??9??18-19?? ???? ??????????2010??9??27-28?? ???? ??????????2010??10??16-17?? ???? ??????????2010??10??23-24?? ???? ??????????2010??10??30-31?? ???? ??????????2010??11??6-7?? ???? ???????????????????????????????????????????????????????????????????? ??????????2470??/??????2???????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ??????????Judge??????????????????????????????????????????????????Harvard???????????????????? Stanford??????????????.????judge??????????????????????????????????????judge???????????????? ?????????????????????????????????????????????????? ?D?D?D?D?D?D???????????????? 1?????????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????????? 5?????????????????????????????????????????????????????? 6?????????????????????????????????????????? 7?????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????? ??????????????????????10?????? 1???????????????????????????????????? 2?????????????????????????????? 3???????????????????????????????? 4?????????????????????????????? 5???????????????????????????????? 6???????????????????????????????? 7?????????????????????????????? 8?????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????????? ??????????????????9?????????? 1?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2???????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3?????????????????????????? ???????????????????????????????????? 4???????????????????????????? ???????????????????????????????????????????? 5?????????????????????????????????????? ???????????????????????????????????? 6?????????????????????????? ???????????????????????????????????????? 7?????????????????????????????? ?????????????????????????? 8?????????????????????????????????? ?????????????????????????????????????? 9???????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ???????????????????????????????????????? ???????????????????????????????? ?????????????????? B???????????????????????????? 1???????????????????????????? 2?????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????? 7???????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ??????????????????????????????! ???????????????????????????? ???????????????????????????? ???????????????????????????????? ??????3???????? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ??????????????????????9???????? ??????????????????????????5???????? ??????????????????????4???????? ????????????,????????????3??????? ??????????,??????????4??????? ?????????????????????????????????????? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ???????????????????????????????????? ????????????????????4???????? ????????????????6?????? ???????????????????????????????? 2???????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ??????????????6?????????? ?????????????? ???????????????????????? ???????????????????????? ???????????????????????? 1???????????????????????????????????? 2???????????????????????????????????????? 3?????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????? ????????.????????.????????EMBA???????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????? ????????????????????????,??????????????????,?????????????????????????????????? ???????????????????????????????????????????????????????????? ---------------------------------------------------------------------------- ??????????2??????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ?????????????????????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From louchan_20344 at tom.com Sat Sep 11 08:34:43 2010 From: louchan_20344 at tom.com (=?gb2312?B?bG91Y2hhbl8yMDM0NA==?=) Date: Sat, 11 Sep 2010 16:34:43 +0800 (CST) Subject: =?gb2312?B?yczO8b/svP48RElWIHN0eWxlPSJESVNQTEFZOiBub25lIj48L0RJVj4=?= Message-ID: <4C8B3F23.000257.07409@cnapp33> { ????????.???????? }??????????.???????????????????????V?????????????????|.????????????????????????????.???????a??.?????????l|????????????( ?????????????????????????????\????????????????????|??????????????????????????????????????????: 1353-069-8196 ????QQ??1621259569 ?????? ?????????????? ???????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From speedpro at bol.com.br Sat Sep 11 14:54:52 2010 From: speedpro at bol.com.br (Adiana Menezes) Date: Sat, 11 Sep 2010 14:54:52 GMT Subject: Tv via Internet 3000 Canais Message-ID: <201009111500.o8BF07a2003828@mx1.redhat.com> An HTML attachment was scrubbed... URL: From pisser at nimsindia.com Sun Sep 12 19:12:45 2010 From: pisser at nimsindia.com (Olynger Stokely) Date: Sun, 12 Sep 2010 21:12:45 +0200 Subject: Reason that she could not explain, she seemed gradually to lo Message-ID: <4C8D25D9.5010606@nimsindia.com> plain woman, by sheer force of soul and wit, can attract friends and make the world forget her ugliness. What made John Blaine's younger daughter an especial favorite was that in her case good looks were allied with brains. She made friends by her natural charm, her vivacity, her keen intelligence and uncommon strength of character, which, despite her youth, she had exhibited on more than one occasion. She was a merry-hearted, spirited, independent kind of a girl with decided views of her own regarding right and wrong and with the courage to express them. As the poet wrote: Her glossy hair was clustered o'er her brow Bright with intelligence and fair and smooth; Her eyebrow's shape was the aerial bow, Her cheek all purple with the beam of youth Mounting, at times, to a transparent glow, As if her veins ran lightning. Two sisters more unlike in character and tastes it would be almost impossible to discover. Fanny, the elder, lacked not only Virginia's good looks, and also her brains. Yet she was good-natured and easy-going, and, as long as she had her own way, managed to get along with everybody. She went through the lower grades of public school, but did not shine as a particularly bright pupil, evincing little love for books, and shirking study when possible. Her fondness for amusement and her uncultivated taste also led to her associating habitually with companions beneath her socially. She was a thoroughly good girl. A vulgar allusion would have shocked her, an impertinence she would have quickly resented; yet she seemed of a coarser fibre than the rest of the family, the reason for which, seeing that both girls had equal advantages and opportunities, only an expert psychologist could explain. She had gone through school mechanically as an unpleasant task to be gotten over with as soon as possible, taking no interest in her work, and when she came out her brain was a sluggish and unresponsive as one might expect. Well aware of her shortcomings, she made light of them, insisting laughingly that she was the dunce of the family and Virginia -------------- next part -------------- A non-text attachment was scrubbed... Name: wafer.jpg Type: application/octet-stream Size: 11725 bytes Desc: not available URL: From georghecasta at yahoo.com Mon Sep 13 12:07:18 2010 From: georghecasta at yahoo.com (Assurance Auto par Liotelex) Date: Mon, 13 Sep 2010 15:07:18 +0300 Subject: Partez bien assure - 2 mois offerts Message-ID: <525c2caa782b40c8471d21606f52553f@m10.goodmarkets67.com> An HTML attachment was scrubbed... URL: From mkt at videosparatreinamento.com.br Mon Sep 13 11:40:04 2010 From: mkt at videosparatreinamento.com.br (Kit Mala Direta - Videos de Treinamento) Date: Mon, 13 Sep 2010 07:40:04 -0400 Subject: =?UTF-8?B?Q29sZcOnw6NvIEVudGVycm8gZGFzIERlc2N1bHBhcw==?= Message-ID: Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://sendmail.videosdetreinamento.com/display.php?M=5390847&C=0dede45aa4dc4c9581d67ff455176ccc&S=188&L=81&N=9 Para parar de receber nossos Emails:http://sendmail.videosdetreinamento.com/unsubscribe.php?M=5390847&C=0dede45aa4dc4c9581d67ff455176ccc&L=81&N=188 Email Marketing -------------- next part -------------- An HTML attachment was scrubbed... URL: From lopezmatienzo at hotmail.com Mon Sep 13 18:24:31 2010 From: lopezmatienzo at hotmail.com (Cesar Lopez Matienzo) Date: Mon, 13 Sep 2010 15:24:31 -0300 Subject: =?utf-8?B?6Z2i5a+5546w5a6e5ZCn77yO77yO77yONTI=?= =?utf-8?Q?o?= Message-ID: ??????? ????????? ????????????????????? ????????? ?????????????? ??????????????????????????????? ???????????????????????????? ??????????? ??? ??????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????? ?????????????? ??????????????????????? ???????????????10????? ???????????????????????????????? ????????????????????? ????????????????? 1. ????????????????????=??????? ??28000? 2. ?????????????????CEO??????? ??15800? 3. ???????????????????????DVD ??29800? 4. ???????????????????????????? ??2980? 5. ??????????????.?????????????????? 6. ??????????????.??08?09??????? ??38000? 7. ????????????? ?????????? ?????? 8. ???????????????????????? 9. ?????????????????????? ??22000? 10.????????????????? ???DVD ??22000? PS??????? ??????? ???????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From yt at oyre.com Mon Sep 13 22:24:34 2010 From: yt at oyre.com (=?GB2312?B?x+vXqsXg0bWyv8PF?=) Date: Tue, 14 Sep 2010 06:24:34 +0800 Subject: =?GB2312?B?z/rK28r9vt231s72?= Message-ID: <201009132224.o8DMOPd0006575@mx1.redhat.com> ?????? - ????? ?????2010?9?16-17? ?? ?????2010?9?18-19? ?? ?????2010?11?19-20? ?? ? ??2600?/???????????????????????????? ?????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------- ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ?????????????? ------------------------------------------------------------------------- ???? ????????????????????Office???Excel???????? ?????????BladeOffice??????????????????????????? ---------------------------------------------------------------------------------- ????: ???? ????????????????????????????????????????????????????... 1.????? 2.???????? 3.?????? 4.???????????????? 5.??????????? ?????? ?????????????????????????????????? ?????????????? ??????????????? 1.?????????? 2.?????? 3.???????? 4.?????? 5.?????? 6.??????????????????????? 7.?????????????? 8.???? ????????????? ????????????????????????????????????????????? 1.??????????? 2.????????? 3.????????? 4.????????? 5.????????? 6.????KPI?? ?????? ????????????????????????????????????? 1.????????? 2.???????? 3.???????? 4.??????? 5.?????? 6.??????? 7.?????? ???????? ????????????????????????????????????? 1.???? 2.??????????? 3.???? 4.??????????? 5.?????????? ???????????? ???????????????????????????????????????????????? 1.?????????? 2.????????????? 3.????????????????? 4.????????? 5.?????????? 6.??????????? 7.????????????? ??????????? ???????????????????????????????????????????????????????????? 1.??????? 2.??????? 3.??????1?1?????? 4.??????????? 5.?????????????? 6.????????RFM?? 7.?????(VOC)?? 8.??????????? 9.??????? ???????? ????????????????????????????????????????????????? 1.????????? 2.??????????? 3.???????????????? i. ???????????????? ii. ??????????? 4.??????????????????????????? i.????????????? ii.???????????? iii.?????????????????????? iv.????????????? 5.???????????????????????? -------------------------------------------------------------------------------------------- ?????????: ??????IPMA???????MCSE?MCDBA?????????????? ??????????????????????????????????????????OA? ERP?BI???????????????????????????????????????? ??????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????????? =============================================================================== ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From rd at trtb.com Tue Sep 14 06:41:32 2010 From: rd at trtb.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Tue, 14 Sep 2010 14:41:32 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs0dC3os3FttO9qMno0+u8pMD4?= Message-ID: <201009140641.o8E6fODe000396@mx1.redhat.com> utrace-devel???????????????????????????????????????? ??????????2010??9??27-28?? ???? ???? ??????????2010??10??19-20?? ???? ???? ??????????????????????????????????????????????????????/??????????/?????????????????????? ??????????2600??/?????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????chinammc2010 at 126.com?????? ---------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? 1???????????????????????????????????????????????????????????????????? 2????????KPI ??????????????????????KPI ???????????????????????????? 3?????????????????????????????????????????????????? 4???????????????????????????????????????????????????????? 5???????????????????????????????????????? 6???????????????????????????????????????????????????????? 7???????????????????????????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????? 11???????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? ================================================================================== ???????? 1?????????????????????????????????????????????????????????????????????????????????????????? 2?????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????? 4???????????????????????????????????????????????????? 5????????????????????????????????????????KPI ???????????????????????????? 6??????????????????????????????????????????PBC?? 7???????????????????????????????????????????????????????? 8???????????????????????????????????????????????????????????????????????????????????? 9??????????20 ?????????????????????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ?????????????????? ???? ?????? ?????????????????????????????????????????????????????????????????? ???????????????????? ==>?????????????????????? ??????????????????????1999???????????????????????????????????????????????????????????????????????? ==>???????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????20???????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? ????????????????????????300??????????????????????????????20??????????????????????????????????????3000?????????? ????????????????????????????????????????????92%????,????????????????????????????????????????????????????,?????? ???????????????????????????????????????????? ====================================================================================== ???????? ???? ?????????????????????? 1. ?????????????????????? a) ?????????????? b) ?????????????? c) ?????????????? d) ???????????? e) ???? 2. ??????????????????PAC??PMT??PDT?? 3. ???????????????????? a) ?????????????????????????????????????????????????????? b) ?????????????????????????????????????? c) ?????????????????????????????????????????????? d) ?????????????????????????????? e) ?????????????????????????????????? f) ?????????????????????????????????? g) ???????????????????????????????????????? h) ?????????????????????????????????????????????? 4. ???????????????????????????? a) ?????????? b) ???????? c) ???????? d) ???????? e) ?????????????????????????????????????????????????????????? 5. ???????????? a) ???????? b) ???????????? c) ???? 6. ???????? ???? ???????????????????????????????????????????? 1. ???????????????????????????? a) ?????????????????????? b) 18???????????? c) ???????????????????????????? * ?????????? * B??E??I????????????????????BEI???????????? d) ???????????????????????????????????????????????? * ???????????????????????????????? e) ?????????????????????????????? * ???????? * ???????? * ?????????? * ???????????? * ?????????????? * ???? 2. ???????????????????????????????? a) ?????????????????? * ???????? * ???????? * ????????????????QA b) ???????????????????????? c) ?????????????????????????????????????? d) ?????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????????????? 2. ???????????????????????????????????????? 3. ???????????????????????????? a) ???????????????? b) ?????????????????????????????????????????? c) ?????????????????? 4. ?????????????????????????? 5. ?????????????????????? 6. ?????????????????????? a) ???????????????????????? b) ????????????????????????????????????????KPI?? 7. ?????????????????????? a) ?????????? b) ?????????????? 8. ???????????????????????????? a) ???????????? b) ?????????????????????????? c) ???????????????????? 9. ?????????? a) ???????????????????????????????????????????? ???? ????????????????????????????????KPI ???????? 1. ????????KPI ???????????????????? 2. ????????????????????????????????????KPI ???? 3. ????????KPI ?????????????? 4. ????????KPI ?????????? a) ???????????????? b) ???????????? 5. ????????KPI ??????????????????I??T??Q??C??S?? 6. ??????????KPI ?????? a) ????????KPI ???? ???????????????????????????????????????????? b) ????????KPI ????????????????????????????????????QA?????? c) ??????????????KPI ????????????HR?????????????????????????? 7. ????????KPI ?????? 8. ?????????????????? a) ???????????????????????????? b) ?????????????????????? c) ??????????????KPI ???????????? d) ?????????????????????????????????????????????? 9. ?????????? a) ????????????????????KPI ?????????????????????????????????????????????? b) ??????????KPI ???????????????????????D?D??????????????PCB ???? ???????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????? a) ?????????????????? b) ?????????????????????????????????????????????????????? 3. ?????????????????? a) ?????????? b) ?????????????????? c) ???????? d) ?????????????? 4. ???????????????????????D?D????????????PBC a) ??????????WINNING?? b) ??????????EXECUTION?? c) ??????????TEAMWORK?? 5. ????????????????PBC ?????????????? 6. ????????????????????????????????PBC 7. ?????????????????????????????? 8. ??????????????????????????PIP?? 9. ?????????? a) ????????????????????????PBC???????? b) ????????????????????????PIP???????? ???? ?????????????????????????????? 1. ?????????????????????????? 2. ?????????????????????????? 3. ???????????????????????????????????????? a) ?????????? b) ?????????? c) ?????????? d) ?????????? 4. ?????????? a) ???????????????????????????????????????????? ???? ???????????????????????????? 1. ?????????????????????????????????????????????? a) ?????????????????????????????????????????? b) ???????????????????????????????????????? 2. ??????????????????????????????????????????HR???????? 3. ?????????????????????????????????????????? 4. ???????????????????????????????????????????????????? 5. ???????????? a) ?????????????????????? b) ???????????????????????????????????????????????????????????? c) ???????????????????????????? d) ?????????????????????????????????? 6. ???????????????????????? a) ?????????????? b) ???????????????????????????????????????????????????????????????????? 7. ?????????????????????? a) ?????????????? b) ?????????????????????????? 8. ???????????????????????????????????????????????? 9. ???????????????????????????????????????????? a) ???????? b) ???????? c) ???????????????? 10. ???????????????????????????????????????? 11. ?????????????????????????????????????????????????? ???? ???????????????????????? 1. ???????????????????????? 2. ?????????????????? a) ?????? b) 5??/10???????? c) ?????? d) ?????? e) ???? f) ???? 3. ???????????????????????????????????????????? 4. ?????????????? a) ??????/?????? b) ?????? c) ?????? d) ?????? e) ?????? 5. ?????????????????????????????????????? 6. ???????????????????????????????????????????????????? -------------------------------------------------------------------- ??????????????????????????????????????????????????????????????020-62351156?? ?????????? ?????? ?????? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638?????? From georghecasta at yahoo.com Tue Sep 14 09:08:59 2010 From: georghecasta at yahoo.com (Assurance Animaux) Date: Tue, 14 Sep 2010 12:08:59 +0300 Subject: Prise en charge de vos frais veterinaires imprevus Message-ID: An HTML attachment was scrubbed... URL: From premiertraining at masteremarketing.com.br Tue Sep 14 09:29:15 2010 From: premiertraining at masteremarketing.com.br (Premier Training) Date: Tue, 14 Sep 2010 05:29:15 -0400 Subject: =?UTF-8?B?UEFHQU1FTlRPIERFIETDiUJJVE9TIFRSSUJVVMOBUklPUyBDT00gRUxFVFJPQlLDgVM=?= Message-ID: <1609a265fb53d972cd415c561d39c516@vailaemail.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Sep 14 16:54:21 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 14 Sep 2010 18:54:21 +0200 Subject: exit_ptrace() && ptrace_report_signal() problems In-Reply-To: <20100914020415.87A9F403E6@magilla.sf.frob.com> References: <201009131859.o8DIx8p1004417@bzweb01.app.bz.hst.phx2.redhat.com> <20100914020415.87A9F403E6@magilla.sf.frob.com> Message-ID: <20100914165421.GB22354@redhat.com> On 09/13, Roland McGrath wrote: > > > It turns out, ptrace_detach_task() is absolutely wrong if > > voluntary == F and the tracee didn't report the stop. > > > > For example, ptrace_report_signal() does: > > > > if (utrace_control(current, engine, UTRACE_INTERRUPT)) > > WARN_ON(1); > > > > this is wrong too. The exiting tracee can do detach in parallel. > > Huh? You mean the exiting tracer can do detach in parallel, right? Argh, tracer, yes. > So utrace_control() inside the callback returns -ESRCH because @engine > is already marked as detached. Yes. > No, of course you must stay around to give back the intercepted signal. > > > But, > > > > ctx->resume = UTRACE_DETACH; > > utrace_barrier(...); > > utrace_control(UTRACE_RESUME); > > > > can't guarantee the tracee won't stop. > > The documented API is that this does guarantee that (if utrace_barrier > returned zero), if you synchronized with the callback. The effect of the > callback's return value should be recorded before utrace_barrier returns. > So you can use barriers or locks to make sure that ->resume is set before > the callback runs or after it runs, and it checks ->resume, then you can > win. If the callback sees ->resume = UTRACE_DETACH, it will know to bail > out and just deliver the new signal. Otherwise, the tracer knows that if > there was a callback, its UTRACE_STOP return value took effect before > utrace_barrier returned zero. The problem is, utrace_control(UTRACE_RESUME) can't prevent the stop if the tracee has already returned UTRACE_STOP, but utrace_stop() didn't take utrace->lock yet. See also below. > > But, even if we fix UTRACE_RESUME, so far I do not see how we can > > fix the implicit detach and avoid the races with report_signal(). > > I am afraid we need some locks. Implicit detach must never use > > UTRACE_DETACH blindly, even if ctx->siginfo/signr = 0. > > Locks just between the tracer and ptrace_report_signal are not bad. OK, but let me think a bit more. I'd really like to avoid adding the new lock to avoid the very unlikely race with the exiting tracer. > I glanced at the patch, but I'd rather see an explanation of its plan. Basically, ptrace_detach_task(sig => -1) should do: - if we are going to do utrace_control(UTRACE_DETACH), we should first instruct the (running) tracee to not report a signal, otherwise that signal will be lost. - if the tracee has already reported a signal, we should set ->resume = UTRACE_DETACH and resume the tracee, like explicit detach does. We can check ctx->siginfo != NULL to detect this case. > Especially if it's as I suspect, that we can do > that without changing the utrace layer. No, this problem is orthogonal, or I missed something. Please look at this message https://www.redhat.com/archives/utrace-devel/2010-June/msg00075.html In particualar: Off hand I think it does matter today insofar as it violates the documented guarantees of the utrace_barrier API. If utrace_barrier returns 0 it is said to mean that, "Any effect of its return value (such as %UTRACE_STOP) has already been applied to @engine." So e.g. if you get a wake-up sent by your callback before it returns UTRACE_STOP, and then call utrace_barrier followed by utrace_control(,,UTRACE_RESUME), then you should be guaranteed that your resumption cleared the callback's stop. Yes, but currently UTRACE_RESUME can't guarantee this. utrace_control(RESUME) should remove ENGINE_STOP like UTRACE_DETACH does, otherwise this code please_never_return_UTRACE_STOP(tracee); // make sure any subsequent callback sees the result of above utrace_barrier(...); // if it has already returned UTRACE_STOP, resume it utrace_control(UTRACE_RESUME); is racy. Oleg. From 4you at marketing4you.com.pt Tue Sep 14 17:01:35 2010 From: 4you at marketing4you.com.pt (4you at marketing4you.com.pt) Date: Tue, 14 Sep 2010 13:01:35 -0400 Subject: No subject Message-ID: <201009141701.o8EH1Z2P030830@mx1.redhat.com> From fatal at telcos.it Tue Sep 14 18:16:49 2010 From: fatal at telcos.it (Pyfer Greenhouse) Date: Tue, 14 Sep 2010 20:16:49 +0200 Subject: Rthward there appeared what looked like the lo Message-ID: <4C8FB65A.3090805@telcos.it> Panish soldier, which he was resolved to wipe out, if possible. These feelings he had wit enough to understand he must conceal from George and the alcalde, and he contrived to do so pretty successfully; but the effort only caused them to gall and rankle the more intolerably, and when, at the termination of his interview with them, he quitted their presence with a certain scarcely veiled hint of insolence in his manner, he was in the throes of a perfect frenzy of anger and humiliation; in the precise frame of mind, in fact, as that of the man who, forgetting everything but his own grievances, is ready to commit any crime, however atrocious, in order to avenge himself and salve his wounded feelings. Too often, unhappily, r -------------- next part -------------- A non-text attachment was scrubbed... Name: crucify.jpg Type: application/octet-stream Size: 12821 bytes Desc: not available URL: From roland at redhat.com Tue Sep 14 19:38:04 2010 From: roland at redhat.com (Roland McGrath) Date: Tue, 14 Sep 2010 12:38:04 -0700 (PDT) Subject: ugdb && breakpoints In-Reply-To: Tom Tromey's message of Friday, 10 September 2010 16:12:12 -0600 References: <20100908191838.GA27120@redhat.com> <20100910220007.GA6587@redhat.com> Message-ID: <20100914193804.99980403E8@magilla.sf.frob.com> The traditional method is to restore the original instruction replaced by the breakpoint in text, single-step over that instruction, then restore the breakpoint in text, then continue. That method requires all-stop so that while you are stepping the thread that just hit the breakpoint, you can't have another thread run past that instruction and miss the breakpoint. Both this traditional in-place method, and the instruction-copying method, depend on using single-step. So "stepi" has to work before "break" can work. Thanks, Roland From oleg at redhat.com Tue Sep 14 19:43:40 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 14 Sep 2010 21:43:40 +0200 Subject: ugdb && breakpoints In-Reply-To: <20100914193804.99980403E8@magilla.sf.frob.com> References: <20100908191838.GA27120@redhat.com> <20100910220007.GA6587@redhat.com> <20100914193804.99980403E8@magilla.sf.frob.com> Message-ID: <20100914194339.GA1979@redhat.com> On 09/14, Roland McGrath wrote: > > Both this traditional in-place method, and the instruction-copying method, > depend on using single-step. So "stepi" has to work before "break" can work. Yes, thanks, I already got it. Oleg. From oleg at redhat.com Tue Sep 14 21:55:14 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 14 Sep 2010 23:55:14 +0200 Subject: exit_ptrace() && ptrace_report_signal() problems In-Reply-To: <20100914165421.GB22354@redhat.com> References: <201009131859.o8DIx8p1004417@bzweb01.app.bz.hst.phx2.redhat.com> <20100914020415.87A9F403E6@magilla.sf.frob.com> <20100914165421.GB22354@redhat.com> Message-ID: <20100914215514.GA8466@redhat.com> On 09/14, Oleg Nesterov wrote: > > On 09/13, Roland McGrath wrote: > > > > Locks just between the tracer and ptrace_report_signal are not bad. > > OK, but let me think a bit more. I'd really like to avoid adding the > new lock to avoid the very unlikely race with the exiting tracer. Oh, please take a look at this (untested) patch. But I think I should make another attempt, probably spinlock (->siglock ?) would be cleaner. Oleg. --- kstub/kernel/ptrace-utrace.c~9_EXIT_PTRACE_CAN_LOSE_SIG 2010-08-24 14:31:17.000000000 +0200 +++ kstub/kernel/ptrace-utrace.c 2010-09-14 23:37:59.000000000 +0200 @@ -67,6 +67,7 @@ struct ptrace_context { #define PT_UTRACED 0x00001000 #define PTRACE_O_SYSEMU 0x100 +#define PTRACE_O_REUSABLE 0x200 #define PTRACE_EVENT_SYSCALL (1 << 16) #define PTRACE_EVENT_SIGTRAP (2 << 16) @@ -115,7 +116,7 @@ ptrace_reuse_engine(struct task_struct * return engine; ctx = ptrace_context(engine); - if (unlikely(ctx->resume == UTRACE_DETACH)) { + if (unlikely(ctx->options == PTRACE_O_REUSABLE)) { /* * Try to reuse this self-detaching engine. * The only caller which can hit this case is ptrace_attach(), @@ -246,24 +247,48 @@ static void ptrace_detach_task(struct ta */ bool voluntary = (sig >= 0); struct utrace_engine *engine = ptrace_lookup_engine(tracee); + struct ptrace_context *ctx = ptrace_context(engine); enum utrace_resume_action action = UTRACE_DETACH; if (unlikely(IS_ERR(engine))) return; - if (sig) { - struct ptrace_context *ctx = ptrace_context(engine); + if (!voluntary) { + int err; + + ctx->resume = UTRACE_DETACH; + /* synchronize with ptrace_report_signal() */ + do { + err = utrace_barrier(tracee, engine); + } while (err == -ERESTARTSYS); + + if (!err) { + /* + * The tracee has already reported a signal. If we + * see ->siginfo != NULL it is safe to mark this ctx + * as reusable and resume the tracee. We can race + * with ptrace_report_signal(UTRACE_SIGNAL_REPORT) + * already in progress but this doesn't matter, it + * must see ->resume = UTRACE_DETACH. + */ + if (ctx->siginfo) { + smp_wmb(); + ctx->options = PTRACE_O_REUSABLE; + action = UTRACE_RESUME; + } + } + } else if (sig) { switch (get_stop_event(ctx)) { case PTRACE_EVENT_SYSCALL: - if (voluntary) - send_sig_info(sig, SEND_SIG_PRIV, tracee); + send_sig_info(sig, SEND_SIG_PRIV, tracee); break; case PTRACE_EVENT_SIGNAL: - if (voluntary) - ctx->signr = sig; + ctx->signr = sig; ctx->resume = UTRACE_DETACH; + smp_wmb(); + ctx->options = PTRACE_O_REUSABLE; action = UTRACE_RESUME; break; } @@ -410,6 +435,9 @@ static u32 ptrace_report_syscall_exit(u3 return UTRACE_STOP; if (ctx->resume != UTRACE_RESUME) { + if (ctx->resume == UTRACE_DETACH) + return UTRACE_RESUME; + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && ctx->resume != UTRACE_SINGLESTEP); ctx->resume = UTRACE_RESUME; @@ -502,6 +530,9 @@ static u32 ptrace_report_signal(u32 acti ctx->siginfo = NULL; if (resume != UTRACE_RESUME) { + if (resume == UTRACE_DETACH) + return action; + WARN_ON(resume != UTRACE_BLOCKSTEP && resume != UTRACE_SINGLESTEP); @@ -531,6 +562,11 @@ static u32 ptrace_report_signal(u32 acti } WARN_ON(ctx->siginfo); + + /* Raced with the exiting tracer ? */ + if (resume == UTRACE_DETACH) + return action; + ctx->siginfo = info; /* * ctx->siginfo points to the caller's stack. @@ -759,7 +795,7 @@ void exit_ptrace(struct task_struct *tra static int ptrace_set_options(struct task_struct *tracee, struct utrace_engine *engine, long data) { - BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + BUILD_BUG_ON(PTRACE_O_MASK & (PTRACE_O_SYSEMU | PTRACE_O_REUSABLE)); ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; From hiv at adwex.com Tue Sep 14 22:51:33 2010 From: hiv at adwex.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 15 Sep 2010 06:51:33 +0800 Subject: =?GB2312?B?VDF1dHJhY2UtZGV2ZWzXqNK1UFBUvLBFeGNlbNOm08M=?= Message-ID: <201009142251.o8EMpX87014029@mx1.redhat.com> utrace-devel???????????PPT+Excel??? ?????2010?10?15-16? ?? ?????2010?10?22-23? ?? ?????2010?10?29-30? ?? ? ??2600?/????????????????? ??????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- PPT?????????PPT????????????? ????????BladeOffice?????????????????? ????????????Excle-PPT??????????BladeOffice???????????????? ?BladeOffice??????????????????? ????: ???????????? ????????????? 1.??????????????????????????? 2.????????????500???????????????? 3.?????????????????????????????????? 4.??????????????????????????????? ??????????? 1.?????????????????? 2.??????????????????150????????? 3.???????????????????????????? 3-D ??*?????? 4.???????????????? ?????????????? 1.??????????????? 2.?????/??????????? 3.????????????????? 4.????????40M?????6M 5.????????? ????????SmartArt???? 1.??????????????? 2.SmartART?????? 3.???????SmartART??? 4.????SmartART???SmartArt?????????????????SmartArt ???????????????? 1.??????????????????? 2.????????? 3.??????????5???? 4.?????????? 5.??????????????? 6.????????????????? ??????????????????? 1.??????????? 2.??????????????????? 3.?????????? 4.???????? 5.??????? 6.????? 7.?????????PPT? 8.???????????? ??????color see see???????? 1.??????Powerpoint????? 2.???CI????????? 3.????????? 4.????????? 5.??????????????? 6.??????????? ???Excel??????? ????????? 1.??????????????? 2.???????????? 3.??????????????? ?????? 1.????Bladeoffice??????????? 2.??????? 3.??????????????? 4.????????????????Excel?? 5.?????????????? ?????????????? 1.??IF??????????? 2.?????????????????? 3.??????????? ?????? 1.?????????? 2.?????? 3.??????????????? 4.????????????? ????????? 1.?????????#DIV?#NAME?#N/A 2.??????#?????????? ???????????? 1.????????????????? 2.???????????????????? 3.???????????????? 4.?????????????????? 5.?????????????? ???????? 1.??????????????? 2.???????????? 3.??????????? 4.?????????????? 5.????????? ?????? 1.????????????????????? 2.??????????? 3.????????? 4.????????????? ????????????? 1.??????????? 2.??????????? 3.Excel2007?????? 4.??????????????? 5.??????????????? ??????????? 1.??????? 2.??????? 3.?????? 4.?????? 5.????????????????????? 6.?????????? a)????? b)????? c)??? d)????? 7.???????????? 8.??????????????????????? 9.????????????????? ?????????? 1.??????????? 2.???????????????? 3.?????????? ??????? ------------------------------------------------------------------------ ????: ????: ??????IPMA???????MCSE?MCDBA?????????????? ??????????????????????????????????????????OA? ERP?BI???????????????????????????????????????? ??????????????????? ??????????? ??????????????? ?????????????? ???????? ?????????????? ?Excel?Access?POWERPOINT?????????? ???????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????? ------------------------------------------------------------------------------- ????????????PPT+Excel???????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From awe at guic.com Wed Sep 15 04:15:27 2010 From: awe at guic.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 15 Sep 2010 12:15:27 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVszve149a00NDBpg==?= Message-ID: <201009150415.o8F4FL3n025636@mx1.redhat.com> utrace-devel????? ?????2010?09?27-28? ?? ?????2010?09?29-30??? ????2680?????????????????????????????? ??????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ?????????????????????????????200????????????????? ??3700????????500?????1000??????2000???????5000?????????? ??????????????????????????????? ??????????????????????????????????????????????? ????????????????1030??????????????5????????????90%? ??????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????? ------------------------------------------------------------------------------------------- ????? 1.????????????????????????? 2.???????????????????? 3.????????????????????????????????? ---------------------------------------------------------------------------------------------- ????? 1.????????????????????????????????????? 2.??????????????????????????????????????? ------------------------------------------------------------------------------------ ????? ????????????? ??? ???????????????? ???????????? ???22??? ??????? ???????????? ?????????? ????????????????? ??????????????? ????????? ?????????????? ????????????? ????????????? ???? ??????? ???????? ????????????? ?????????? ?????????? ?????????? ????????????? ?????????????? ????????? ????????? ????????? ???????????????? ????????????? ?????????????? 80/20?? ???????? ?????? ????? ????????????? ??????????????? ?????????? ?????????????? ?????????? ???????????? ???? ???? ???? ?????????????????? ??????????? ???????????? ????????????? ????????? ??????????? ????????? ???? ???? ???? ????? ???????? ??????? ??????????? ???? ???? ???? ???16??? ???24??? ??????? ????????????? ????????????????? ?????????????? ???GE?????????? ????????????? ??????????? ????????? ????????? ????????? ????????? ????????????? ???????????? ???????????? ???????????? ?????????? ??????? ???? ???? ????????? ????????????????? ?????????????? ????????????? ????????????? ????????????? ????????????? ???????????????? ??????&??????? ??????????????? ??????? ??????? ??????? ??????? ??????????? ????????????? ????????????????? ?????????? ??????????????? ???????????? ????????????? ???????????? ?????????????????? ????????????????? ???????? ???? ???? ???? ???? ???? ????????4P?? ?????????? ??????????? ?????????? ??????????????? ??????????? ??????? -------------------------------------------------------------------------- ????????????GEC??????????????PTT???????????? ???????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????04?????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ???????????????????????????HR??????????????? ???????? ??????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????TCL???????? ????????? -------------------------------------------------------------------- ????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From erg at buk.com Wed Sep 15 15:13:21 2010 From: erg at buk.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Wed, 15 Sep 2010 23:13:21 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsvbW1zbLJubqzybG+vLC5qdOmyczMuMXQ?= Message-ID: <201009151513.o8FFDFAF015855@mx1.redhat.com> utrace-devel?????????????? ?????2010?10?9-10? ?? ?????????2500?/?????????????????? ????? ?????????????????????????????????. ???????600?/?;??800?/?(??????????????) ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ????? ?????????????????????? ????????????????????????????? ?????????????? ???????????????? ????????????? ??????????? ------------------------------------- ????? ?????????????? ????????????? ??????????? ????????????????? ??????????????? ??????????????? ?????????? ?????????? ????????? ------------------------------------- ???? ?????????????????? ??????????????? ?????KPI?????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ????????????? ????????????? ???? ?????? ?????? ???? ??????????????? ??????????????? XX??2009?????? ??????????? ?????????? ?????????????? ?????????? ????????????????? ????????????? ??????? ????????????? ???????????? ??????????? ??????????????? ?????????????? ???????????? ????????? ????????? ??????? ?????????????????? ??????????? ?????-??????? ????? ????????????? ?????????? ??????? ?????????????? ?????????? ??????????? ??????????????? ?????????? ????????(???)???? ???????????? ????????????? ?????????? ?????????? ??????? ?????? ??????????? ??????????????????? ??????? ?????????????? ????? ??????????????? ?????? ???????????????? ????????????? ?????????? ?????????????? ??????????? ???????????????? ??????????? ??????????? ?????????????? ??????????????? ?????????????????? ??????????? ??????????? ??????? ?????????????? ???? ???? ??????? ?????????? ???????? ??????????? ???????? ??????? ?????????? ????????? ?????????????? ??(??)??????? ???????????? ??????????? ????????? ???????? ?????????? ????????? ???????????????? ??????????? ???????????? ?????? ??????? ?????????? ???????? ????????? ????? ???????????? ????????????????????? ???????????? ??????? ?????????? ???????????? ??????????? ???????????? ????????? ?????????? ?????????????? ??????????? ????? ???????? ???? ?????????? ???????? ???????? ??????? ??????????????? ????????????? ??????????? ???????? ??????????? ?????????????????? ??????????????? ?????KPI?????? ??????????? ?????????????? ???????? ????? ???????????????? ?????? ????????????????? ??????????? ??????????? ????????????? ???Pareto(???)??? ABC??? ???????????????? ??????????????? ??????????????? ????????????? ????????????ff ?????????? ???????? ????????????? ?????????????? ?????????????? ????????VMI?? ???JIT???? ???????????? ??????? ???JIT? JIT?JIC??? JIT?????JIT??????? ?????????? ???????????? ??????? (VMI) ?????? ?????? ------------------------------------------------------------------------------ ??????????? 1986????Gerber?????????Michigan State University (???????) ????????????,?????Heinz(??)??????????????????????????? ?????????????????????????????2000???,???????????????? ?????????,???????500??????????????,?????????????????? ??????????????????????????????????????????????????? ??????????? ??????????????????????????????????????? ?????????????????????????????????????????????????? ????? ?????????????,?????????,??,???????????,?????,?? ???????????????????????????????,??????????????,???? ????????????????? ---------------------------------------------------------------------------------------------- ????? ????????????020-62351156 ??????? ????? 2010?___________ ? ______ ??? ??????????????? ??????????????????????????????????????????? ??????????????? ?????????????? ????????????? ????????????????? ??????????????????????? ????????? ? ??????????? ? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? ? ? ?????????? ??????????????? ?????????????? From tro at ihix.com Wed Sep 15 15:24:49 2010 From: tro at ihix.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 15 Sep 2010 23:24:49 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVss7W85Nb3udy53MDtxNzBpszhyf0=?= Message-ID: <201009151524.o8FFOjUl011346@mx1.redhat.com> utrace-devel??????????? ?????2010?9?17-18? ?? ?????2010?12?11-12? ?? ? ??2200?/? ????????????????? ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc2010 at 126.com??? ----------------------------------------------------------------------------------------------- ??????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????. ??????????????????????????????????????????????? ??????????????????????????????????????????????! ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? -------------------------------------------------------------------------------------------- ???????????? l?????????????????????????????????????????? 2??????????????????????????????? 3?????????????????????????????????????????? 4????????????????????????????????????????????? 5???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? -------------------------------------------------------------------------------------------- ????? l??????????????????????????????? 2??????????????????? 3????????????????????? 4???????????????????????????? 5??????????????TPM???????? ????? l????????????????????????? 2???????????????????????????????????? 3???????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????? ??????????????? ??????????? ????????????????? ????????????? ?????/?????/????? ?????????????? ??????????? ????????????? ????????????? ???????????????? ????????????????? ???????????????? ???????????????? ???????????? ???????????? ??????????????? ???????????? ??????????? ?????????????? ???????????????? ??????????????? ???????(?????) ?????????????? ????????? ??????????? ????????? ??????????? ????????????? ??:??????????? ???? ??N?????/??????? ???ISO9000??????????? ??????????????? ????????????????TPS? ???????????TOYOTA??? ????????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ????TQM?6?????????? ????????????????????????? ??????????????????? ??????????????? ???TPM??????????????????? ???TPM????????? ???: ???? ???? ??????????? ??????????? ?????????? ????????? ????????? ??: ??????????? ?????????????? ??????? ?????????????????? ??????????? ??????????????? ---???????????,??????????????) ---????????? ---????????? ---???????????? ??????/????????????; ???? 1.??????????????? 2.?????????? ?????????????????; ---???????????? ------------------------------------------------------------------------------------------------------------- ?????????? ?????? ???????? ???????????????(SUMIDA)????????(CASIO) ???13??????????????????????????????????????????????? ??WF&IE ???????????????????????????????????????????????????????JIT ??????NPS????????????? ??????????????(??,??,??,??,?????)????? ?:??????????ST?????????????????????????????????????????????? ???????????????????????????????80?????? ?????????????????????????????????????????????ABB?????????? ?????-??????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ?????????????????????????????? ??????????????????,?????????????????????????????????????? ?????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From linda_00love at att.net Wed Sep 15 16:20:33 2010 From: linda_00love at att.net (linda godwill) Date: Wed, 15 Sep 2010 09:20:33 -0700 (PDT) Subject: Hello Message-ID: <771202.15147.qm@web83709.mail.sp1.yahoo.com> Hello My name is miss Linda I am interested in your friendship, I would also like to know something about you. I want you to send a mail so I can give you my picture for you to know whom l am. I think we can move on from here. I am waiting for your mail (Remember the distance or color does not matter, but love matter a lot in lif Please reply me Thanks, ????? LINDA -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Sep 15 19:47:47 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 15 Sep 2010 21:47:47 +0200 Subject: exit_ptrace() && ptrace_report_signal() problems In-Reply-To: <20100914215514.GA8466@redhat.com> References: <201009131859.o8DIx8p1004417@bzweb01.app.bz.hst.phx2.redhat.com> <20100914020415.87A9F403E6@magilla.sf.frob.com> <20100914165421.GB22354@redhat.com> <20100914215514.GA8466@redhat.com> Message-ID: <20100915194747.GA4073@redhat.com> On 09/14, Oleg Nesterov wrote: > > Oh, please take a look at this (untested) patch. I tried to test the cleanuped version, seems to work. > But I think I should make another attempt, probably spinlock (->siglock ?) > would be cleaner. No. I think more locking buys nothing. I'll split this patch and resend today. Oleg. From cornel at upload-ro.ro Wed Sep 15 22:56:07 2010 From: cornel at upload-ro.ro (oferta cursuri de perfectionare) Date: Thu, 16 Sep 2010 01:56:07 +0300 Subject: oferta cursuri de perfectionare Message-ID: <20100915.NEJIPLKLRZVHHGBS@upload-ro.ro> An HTML attachment was scrubbed... URL: From contato1217 at armandohenrique.com.br Wed Sep 15 23:05:52 2010 From: contato1217 at armandohenrique.com.br (Armando Henrique) Date: Wed, 15 Sep 2010 20:05:52 -0300 Subject: Propostas de trabalho I Message-ID: <7a35e81588d96c16ef7314ee097713a2@localhost.localdomain> Caso n?o visualize esse email adequadamente VIEW_LINK http://armando1217.entregadordenoticias.net/ver_mensagem.php?id=H|1106|52295|128458467537939100acesse este link[/VIEW_LINK] Se voc? n?o deseja mais receber nossos e-mails, cancele sua inscri??o atrav?s do link http://armando1217.entregadordenoticias.net/admin/sair.php?id=52295|1106|0&uid=128458467537939100 -------------- next part -------------- An HTML attachment was scrubbed... URL: From hco at uerg.com Thu Sep 16 07:58:06 2010 From: hco at uerg.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 16 Sep 2010 15:58:06 +0800 Subject: =?GB2312?B?QTF1dHJhY2UtZGV2ZWzP+srbvqvTorXEvKTA+A==?= Message-ID: <201009160758.o8G7w5fQ025522@mx1.redhat.com> utrace-devel????????2?????????? ???????????????????????????????????????????????????????????????????????????? ??????????2010??9??18-19?? ???? ??????????2010??9??27-28?? ???? ??????????2010??10??23-24?? ???? ??????????2010??10??30-31?? ???? ??????????2010??11??6-7?? ???? ??????????2010??11??13-14?? ???? ???????????????????????????????????????????????????????????????????? ??????????2470??/??????2???????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ??????????Judge??????????????????????????????????????????????????Harvard???????????????????? Stanford??????????????.????judge??????????????????????????????????????judge???????????????? ?????????????????????????????????????????????????? ?D?D?D?D?D?D???????????????? 1?????????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????????? 5?????????????????????????????????????????????????????? 6?????????????????????????????????????????? 7?????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????? ??????????????????????10?????? 1???????????????????????????????????? 2?????????????????????????????? 3???????????????????????????????? 4?????????????????????????????? 5???????????????????????????????? 6???????????????????????????????? 7?????????????????????????????? 8?????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????????? ??????????????????9?????????? 1?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2???????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3?????????????????????????? ???????????????????????????????????? 4???????????????????????????? ???????????????????????????????????????????? 5?????????????????????????????????????? ???????????????????????????????????? 6?????????????????????????? ???????????????????????????????????????? 7?????????????????????????????? ?????????????????????????? 8?????????????????????????????????? ?????????????????????????????????????? 9???????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ???????????????????????????????????????? ???????????????????????????????? ?????????????????? B???????????????????????????? 1???????????????????????????? 2?????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????? 7???????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ??????????????????????????????! ???????????????????????????? ???????????????????????????? ???????????????????????????????? ??????3???????? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ??????????????????????9???????? ??????????????????????????5???????? ??????????????????????4???????? ????????????,????????????3??????? ??????????,??????????4??????? ?????????????????????????????????????? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ???????????????????????????????????? ????????????????????4???????? ????????????????6?????? ???????????????????????????????? 2???????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ??????????????6?????????? ?????????????? ???????????????????????? ???????????????????????? ???????????????????????? 1???????????????????????????????????? 2???????????????????????????????????????? 3?????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????? ????????.????????.????????EMBA???????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????? ????????????????????????,??????????????????,?????????????????????????????????? ???????????????????????????????????????????????????????????? ---------------------------------------------------------------------------- ??????????2??????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ???????????????? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From perceivably at allenface.com Thu Sep 16 18:54:10 2010 From: perceivably at allenface.com (Haist Debona) Date: Thu, 16 Sep 2010 20:54:10 +0200 Subject: ll. There's no Message-ID: <4C926751.6010205@allenface.com> N he said, "I am told, and I believe it, that no man ever really gets over having been imprisoned." _Evening_. I feel greatly refreshed, for what do you think I've been doing since I left off writing this morning? Motoring out into the country,--the sweet and blessed country, the home of God's elect, as the hymn says, only the hymn meant Jerusalem, and -------------- next part -------------- A non-text attachment was scrubbed... Name: clericalism.jpg Type: application/octet-stream Size: 11044 bytes Desc: not available URL: From odontoclube at masteremarketing.com.br Wed Sep 15 15:23:48 2010 From: odontoclube at masteremarketing.com.br (Odonto Clube) Date: Wed, 15 Sep 2010 11:23:48 -0400 Subject: =?UTF-8?B?UHJvcG9zdGEgSXJyZWN1c8OhdmVs?= Message-ID: [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=30&F=T] S? a ODONTO CLUBE consegue reunir em um PLANO ODONTOL?GICO, qualidade, maior rede de servi?os com mais de 13.000 cl?nicas e um pre?o que voc? pode pagar! Voc? ainda ganha PRESENTE DE BOAS VINDAS! [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=31&F=T] [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=32&F=T voltado para todas as pessoas, empresas a partir de 03 vidas ou profissionais liberais. [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=33&F=T a partir de R$ 38,90 (individual) e R$ 14,90 (empresarial). [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=34&F=T p?blicos, Banco do Brasil, Caixa Econ?mica, BB Turismo, Advogados, Policiais, Trabalhadores do com?rcio, entre outros. [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=35&F=T] [http://vailaemail.com.br/email/link.php?M=2460361&N=52&L=36&F=T] -------------- next part -------------- An HTML attachment was scrubbed... URL: From m_diaz_gallego at hotmail.com Fri Sep 17 10:12:15 2010 From: m_diaz_gallego at hotmail.com (marian diaz gallego) Date: Fri, 17 Sep 2010 12:12:15 +0200 Subject: =?gb2312?B?wb3M7MO7zbWyy6OsvrnIu9eswcs=?= =?gb2312?B?Nc3yv+mjoaOho6GjoQ==?= Message-ID: ??????? ???????B???????????????????????????X?????? ??? ????M??????????????????X?????????????????? ??? ???????K???????????????????????????N?????? ???????????????U?????????? ???????C?????????? 1.???24???Y10???? ????? 2.????G????9????? ????? 3.???R????7????? ????? ?????????????8????????????I????????????? ???L???? ps????????????Y??????????M????? ?????N?????????????J-??17???T??? ????????????L??????????R% -------------- next part -------------- An HTML attachment was scrubbed... URL: From viash3 at hotmail.com Fri Sep 17 13:24:41 2010 From: viash3 at hotmail.com (Viri Astorga) Date: Fri, 17 Sep 2010 08:24:41 -0500 Subject: =?gb2312?B?yOe6zsjD19TS0bXEyfq77rj8w8A=?= =?gb2312?B?usOjoW0=?= Message-ID: ?????? ????????,"?????????????????? ?????????????? ???????????? ???????????? ??????????? ??????????????? ?? ??????????????????????????????? 1. ???????????????2980???????????????? 2. ????????????? ?????????? ?????? 3. ????6?8?????????????DVD 4.??????????6800?????????????????DVD 5.??????? ??? ?????????????14????????????58000??????????????? ??????? ??????? ps??????10??????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From premier_05 at masteremarketing.com.br Fri Sep 17 01:56:16 2010 From: premier_05 at masteremarketing.com.br (Premier Training) Date: Thu, 16 Sep 2010 21:56:16 -0400 Subject: =?UTF-8?B?QVMgSE9MRElOR1MgTk8gUExBTkVKQU1FTlRPIFNVQ0VTU8OTUklPIEUgTkEgUFJPVEXDh8ODTyBERSBQQVRSSU3DlE5JTw==?= Message-ID: <3f2772f399a42fdc17b79c9da0a32c87@vailaemail.com.br> An HTML attachment was scrubbed... URL: From wsu at ydsc.com Fri Sep 17 18:16:53 2010 From: wsu at ydsc.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sat, 18 Sep 2010 02:16:53 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVszve149a00NDBpg==?= Message-ID: <201009171816.o8HIGo8s009035@mx1.redhat.com> utrace-devel????? ?????2010?09?27-28? ?? ?????2010?09?29-30??? ????2680?????????????????????????????? ??????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ?????????????????????????????200????????????????? ??3700????????500?????1000??????2000???????5000?????????? ??????????????????????????????? ??????????????????????????????????????????????? ????????????????1030??????????????5????????????90%? ??????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????? ------------------------------------------------------------------------------------------- ????? 1.????????????????????????? 2.???????????????????? 3.????????????????????????????????? ---------------------------------------------------------------------------------------------- ????? 1.????????????????????????????????????? 2.??????????????????????????????????????? ------------------------------------------------------------------------------------ ????? ????????????? ??? ???????????????? ???????????? ???22??? ??????? ???????????? ?????????? ????????????????? ??????????????? ????????? ?????????????? ????????????? ????????????? ???? ??????? ???????? ????????????? ?????????? ?????????? ?????????? ????????????? ?????????????? ????????? ????????? ????????? ???????????????? ????????????? ?????????????? 80/20?? ???????? ?????? ????? ????????????? ??????????????? ?????????? ?????????????? ?????????? ???????????? ???? ???? ???? ?????????????????? ??????????? ???????????? ????????????? ????????? ??????????? ????????? ???? ???? ???? ????? ???????? ??????? ??????????? ???? ???? ???? ???16??? ???24??? ??????? ????????????? ????????????????? ?????????????? ???GE?????????? ????????????? ??????????? ????????? ????????? ????????? ????????? ????????????? ???????????? ???????????? ???????????? ?????????? ??????? ???? ???? ????????? ????????????????? ?????????????? ????????????? ????????????? ????????????? ????????????? ???????????????? ??????&??????? ??????????????? ??????? ??????? ??????? ??????? ??????????? ????????????? ????????????????? ?????????? ??????????????? ???????????? ????????????? ???????????? ?????????????????? ????????????????? ???????? ???? ???? ???? ???? ???? ????????4P?? ?????????? ??????????? ?????????? ??????????????? ??????????? ??????? -------------------------------------------------------------------------- ????????????GEC??????????????PTT???????????? ???????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????04?????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ???????????????????????????HR??????????????? ???????? ??????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????TCL???????? ????????? -------------------------------------------------------------------- ????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From retornando at emailmkt.cartmegas.com Fri Sep 17 18:48:35 2010 From: retornando at emailmkt.cartmegas.com (Mauricio Novaes) Date: Fri, 17 Sep 2010 18:48:35 GMT Subject: Tv via Internet 3000 Canais Message-ID: <201009171848.o8HImbBd017890@mx1.redhat.com> An HTML attachment was scrubbed... URL: From roland at redhat.com Fri Sep 17 23:48:34 2010 From: roland at redhat.com (Roland McGrath) Date: Fri, 17 Sep 2010 16:48:34 -0700 (PDT) Subject: exit_ptrace() && ptrace_report_signal() problems In-Reply-To: Oleg Nesterov's message of Tuesday, 14 September 2010 18:54:21 +0200 <20100914165421.GB22354@redhat.com> References: <201009131859.o8DIx8p1004417@bzweb01.app.bz.hst.phx2.redhat.com> <20100914020415.87A9F403E6@magilla.sf.frob.com> <20100914165421.GB22354@redhat.com> Message-ID: <20100917234834.A4FC1403E8@magilla.sf.frob.com> > The problem is, utrace_control(UTRACE_RESUME) can't prevent the stop if > the tracee has already returned UTRACE_STOP, but utrace_stop() didn't > take utrace->lock yet. So you are saying that utrace_barrier does not meet its documented API. Right? It says "effect ... has been applied". But that's not true if a UTRACE_STOP return value will not be cleared by an immediate subsequent utrace_control(,,UTRACE_RESUME). > Basically, ptrace_detach_task(sig => -1) should do: > > - if we are going to do utrace_control(UTRACE_DETACH), we > should first instruct the (running) tracee to not report > a signal, otherwise that signal will be lost. Right. > - if the tracee has already reported a signal, we should > set ->resume = UTRACE_DETACH and resume the tracee, like > explicit detach does. Right. > We can check ctx->siginfo != NULL to detect this case. Ok. > > Especially if it's as I suspect, that we can do > > that without changing the utrace layer. > > No, this problem is orthogonal, or I missed something. > > Please look at this message > > https://www.redhat.com/archives/utrace-devel/2010-June/msg00075.html Yes, I'd forgotten about that. We do need to fix utrace_barrier to match its documented guarantee, or else we cannot rely on it for ptrace. > In particualar: > > Off hand I think it does matter today insofar as it violates the > documented guarantees of the utrace_barrier API. If utrace_barrier > returns 0 it is said to mean that, "Any effect of its return value (such > as %UTRACE_STOP) has already been applied to @engine." So e.g. if you > get a wake-up sent by your callback before it returns UTRACE_STOP, and > then call utrace_barrier followed by utrace_control(,,UTRACE_RESUME), > then you should be guaranteed that your resumption cleared the > callback's stop. > > Yes, but currently UTRACE_RESUME can't guarantee this. >From the API perspective I had been thinking in, it's not utrace_control that's supposed to guarantee it. It's utrace_barrier that's not supposed to return yet. But, that is indeed a sort of inside-out way of looking at it, really. What utrace_barrier guarantees is that the callback bookkeeping is done, and it's not supposed to wait for e.g. the next engine's callback to run. > utrace_control(RESUME) should remove ENGINE_STOP like UTRACE_DETACH does I think you've now talked me into this. There is no other way that utrace_barrier can keep its guarantee about the return value effect without also delaying while other engines' callbacks might run, which seems much worse. Thanks, Roland From tfernandes at steveandbarrys.com Sat Sep 18 22:08:48 2010 From: tfernandes at steveandbarrys.com (tw) Date: Sun, 19 Sep 2010 06:08:48 +0800 Subject: =?gb2312?B?xvNg0rXWtGDQ0MGmYMzhYMn9sr1g1uhsLi8n?= Message-ID: <20100919060858803410@steveandbarrys.com> << ?#?+?$?#?&?^?%?#? >> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ? ? ? ? ?.doc Type: application/msword Size: 39936 bytes Desc: not available URL: From bfr at rfer.com Sun Sep 19 03:24:57 2010 From: bfr at rfer.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Sun, 19 Sep 2010 11:24:57 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsxvPStcTasr/J87zGvLC358/V?= Message-ID: <201009190324.o8J3Or32012954@mx1.redhat.com> utrace-devel???????????????? ?????2010?9?25-26? ?? ?????2010?9?29-30? ?? ????: ?????????;???????????????????;???????? ??????????????;??????????????????????????? ??????????????? ????: 2600?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ??????????????chinammc2010 at 126.com??? ====================================================================================== ???? ??????????????? ??????????????? ??????????????? ???????????? ????????????????????? ?????????????????????????? ?? ????????????????????????????????????????????? ????????????????????????????????????????????? ??????????????????????????????? ================================================================================== ???? ??????????????????????????????????????????????? ????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????? ??????????????????????? ??????????????????????????? ????????????????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA????? ????CPA????????CPT???????????????????????????????? ??????????????????????????????????????????????? ???????????????CFO??????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????,??????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????(??)??????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????????????????????? ????????????????? ???????????????????? ====================================================================================== ???? ????? ??????????? ?????????? 1??? 2??? 3????????????? ???????????? 1??? 2????? 3????? 4????????? ?????????? 1???? 2???? 3???? 4???? ????????? 1????? 2??????? 3???????? 4???????? 5?????? ????????? 1??????? 2????? 3??????? 4????? ?????????????????????? 1?????????????? 2????? 3????????? 4?????????????????? 5????? 6????? 7??????? 8????? 9??????? ???????????? 1??????? 2??????????? 3????? 4??????? 5????? 6?????? 7?????? 8??????? 10????? 11????????????? 12???????????????????? 13?????????? 14?????? 15?????? 16?????? ?????????????????? 1???????????? 2?????????????? 3???????????? ????? ???????? ?????????? 1?????????? 2?COSO????? 3???????? ?????????? 1????? 2??????? 3????? 4???????? 5?????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? ???????????? 1????? 2????? 3????? 4????? 5????? ??????????? 1????????????????????? 2??????? ?????????? ?????????? ??????????? 1??? 2????? 3????? 4????? 5?????? 6????? ??????????? 1??? 2????????????? 3????????????? 4?????????????? ??????????? 1??? 2??? 3??? 4??? 5????? 6????? 7????? 8??????? 9??? 10??? 11????? 12??? 13????? 14????? 15???????? 16?????????? 17??????? 18????????? 19????? 20????? 21????? 22????? ???????? ?????????? 1??????? 2?????? 3??????? 4?????? 5???????? 6????? ??????????????????? 1??????? 2????? 3??? 4????? ?????????????????????? 1???????? 2???????? 3???????? 4????? 5????????????? 6????????????? 7??????? 8????? ???????? 1?????????? 2???????? 3????????? 4????? 5???????????? ???????? ?????????? 1????? 2????? 3????? 4????? 5????? 6????? 7????? 8????? 9????? 10????? 11????? 12????? 13????? ???????????? 1??????? 2??????? 3??????? 4??????? ??????????? 1??????? 2??????? 3??????? 4??????? 5????????? 6????????? 7????????? 8??????????? 9??????? 10??????? 11????????? 12??????? 13??????????? 14????????? ???????????? 1?????????? 2?????????????? 3???????????????? ???????????????????? 1????? 2????? 3????? 4????? ???????? ??????????????????????? ???????????? 1???????? 2????????????? ?????????? 1????? 2????? 3??????? 4???????? ?????????? 1???? 2???? 3????? 4???? ????????????? 1????? 2????????????? 3??????? 4????????? ???????????? ???????????Z-SCORE??? ??????????????? 1???? 2???? 3???? 4???? ---------------------------------------------------------------- ?????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From tl at mete.com Sun Sep 19 16:12:59 2010 From: tl at mete.com (=?GB2312?B?x+vXqsjLysKyvw==?=) Date: Mon, 20 Sep 2010 00:12:59 +0800 Subject: =?GB2312?B?uN/Qp7LWtKK53MDt?= Message-ID: <201009191613.o8JGCw19008645@mx1.redhat.com> ????????????? ?????2010?9?28-29? ?? ?????2010?10?25-26? ?? ?????2010?11?26-27? ?? ?????2010?12?10-11? ?? ?????????????????????????????????????? ?????2800?/????????????????????? ?????020-80560638?020-85917945?????????????????chinammc2010 at 126.com??? -------------------------------------------------------------------------------------- ??????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????? ??????????? ????????? ??????????? ?????????? ???????????? ????????? ????????? ???????? ????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????? --------------------------------------------------------------------------------------------- ?????????????????????????1986????Gerber?????????Michigan State University (??????) ???????????,?????Heinz(??)????? ??????????????????????????????????????????????? ????2000???,????????????????????????,???????500????? ????????,??????????????????????????????????????? ???????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????ABB?????????????????????,?????????,??,? ??????????,?????,???????? ---------------------------------------------------------------------------- ??????????????????? ????????????? ??????????????? ???????????????-KPI? ???????? ?????????????? ????????????????? ????????????? ?????????????????????????? ??????????????? ?????KPI??? ???????????? ?????????? ????? ?????????? ????????? ??????????? ???????? ??????????? ??????? ????????? ??????????????????? ????????????? ??????????? ???????? ?????KPI????? ????????? ??????? ??????????? ??????????? ?????????? ????????????????????? ????????????????? ??????????????? ???KPI?????? ?????????? ??????? ?????????? ??????? ???????? ??????????? ??????????????? ????????????????? ?????KPI??? ???????????? ??????? ????????????? ????????????? ????????? ??????????? ?????KPI????? ??KPI??? ?????????? ??????????? ?????????? ?????????????? ????JIT? ???????????????????? ??????????????????? ???????????? ?????KPI?????? ?????????????? VMI??????? VMI????? "?????? " "?????? ????????????? "?????????????? ?????????KPI????? ???????KPI??? ????KPI?????? ?????? ???????????? ?????????????? ???????? ?????????????????? "?????????????? ????????KPI?????? ??????????? ?????????? ????????? ??????? ???????? ?????????? ??????????? ????????? ?????????????? ????????? ?????????????? ?????? ????? ??????????? ???????????? ?????????? ???????? ???????????????? "?????????????????? " ??????????????? ????????? ????????? ???????? ????????? ?????????? ??????????? ??????? ????????? ?????????????? ???????????????? ??????????????? ??????????? ???????? ?????????????? ?????????????? ??????? ??????????? ??????? ??????????? ???????? ??????????? ??????????????? ????? ??????????????5S??? ??????????? ???????? ???????????????????? ???????????????? ??????????? ??????? ???? ?????? ????? ????? ????? ????????? ???????????????? ?????????????? ??????? ????? ?????????? ????????? ???????? ??? ??????? ???? ???? ?????????????? ?????KPI? ????????? ??????? ?????????? ??????? ?????????? ??????? ??????????? ????:???????? ???????????????????? ???????? MRP II?DRP?ERP ?????? ?????? ??????????? ???????? ??????????? ????? ????????? RFID? ?????RFID? GPS?POS ?????????????????????? ?????RFID???????? ERP???????????????? ------------------------------------------------------------------------------------ ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From oleg at redhat.com Mon Sep 20 03:27:41 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 20 Sep 2010 05:27:41 +0200 Subject: gdbstub initial code, v10 Message-ID: <20100920032741.GA24882@redhat.com> Back to ugdb. Changes: implement stepi, this also means breakpoints work too. Notes: - almost untested, probably needs more fixes - syscall-stepping doesn't work correctly (should be simple) - don't look at handle_setregs/handle_set_one_reg, I did this on purpose to be sure I really understand what gdb actually does Well. This wasn't simple because I nearly got heart attack twice when I was writing this change ;) However, it turns out that ptrace-utrace (old or recently changed) is innocent. I found 2 problems, the 1st one is /usr/bin/gdb bug, another one (I believe) is utrace core bug. I'll report tomorrow. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; bool t_step; // XXX: move me into t_stop_event siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all, bool step) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { unsigned long events = 0; enum utrace_resume_action action = UTRACE_RESUME; thread->t_step = step; if (step) { // events |= UTRACE_EVENT(SYSCALL_EXIT) action = UTRACE_SINGLESTEP; } // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, events); ugdb_control(thread, action); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; if (thread->t_step) { // user_single_step_siginfo(current, regs, info); memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; break; } /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (thread->t_siginfo) { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); if (thread->t_step) return UTRACE_SINGLESTEP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL, false); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; bool step; step = (*cmd == 'S' || *cmd == 's'); switch (*cmd++) { case 'C': case 'S': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': case 's': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; /* * Otherwise I do not know what to do if sig/step, and anyway * I don't think gdb can try to cont a thread which was not * reported as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false, step) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_setregs(struct ugdb *ugdb, char *cmd) { printk(KERN_INFO "ugdb: unexpected $G packet.\n"); return ""; } static const char *handle_set_one_reg(struct ugdb *ugdb, char *cmd) { unsigned int reg; long val; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "%x=%lx", ®, &val) != 2) goto err; if (reg != 0x10 && reg != 0x39) { printk(KERN_INFO "ugdb: unknown reg %x\n", reg); goto err; } // XXX: Hmm. val = be64_to_cpu(val); // DO NOT LOOK AT THIS TEMPORARY CODE task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; if (reg == 0x10) task_pt_regs(task)->ip = val; else if (reg == 0x39) task_pt_regs(task)->orig_ax = val; ugdb_finish_examine(ugdb, &exam); return "OK"; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } // XXX: hex_to_bin() after 90378889 commit #include static int cap_hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; hi = cap_hex_to_bin(*cmd++); lo = cap_hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'G': rc = handle_setregs(ugdb, cmd + 1); break; case 'P': rc = handle_set_one_reg(ugdb, cmd + 1); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': case 'S': case 's': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From premier_02 at masteremarketing.com.br Sun Sep 19 22:39:19 2010 From: premier_02 at masteremarketing.com.br (Premier Training) Date: Sun, 19 Sep 2010 18:39:19 -0400 Subject: =?UTF-8?B?QVMgSE9MRElOR1MgTk8gUExBTkVKQU1FTlRPIFNVQ0VTU8OTUklPIEUgTkEgUFJPVEXDh8ODTyBERSBQQVRSSU3DlE5JTw==?= Message-ID: <6e864722ff408805fe0a5387d12c107e@vailaemail.com.br> An HTML attachment was scrubbed... URL: From alirubio7 at hotmail.com Mon Sep 20 15:56:47 2010 From: alirubio7 at hotmail.com (Julia Alicia Rubio Caldern) Date: Mon, 20 Sep 2010 10:56:47 -0500 Subject: =?gb2312?B?yOe6zsjDxOPJ+rvuuPy+q7LKo6E=?= =?gb2312?Q?l5H?= Message-ID: ? ?????? ????????," ??????????????? ?6??????????? ?????????????????????????????????????? ?????????????????????????????????????? ????????????? 1. ?????????????.?????????????????? 2. ??????????????.??08?09??????? ??38000? 3. ????????????????DVD ??6?8?? 4. ???????????????????????DVD ??29800? 5.???????????????????????DVD ??6800? ?????????????13???????????78690?? ????????????? ??????? ??????? ps???????????????????????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: From perfects at post.comunit.de Mon Sep 20 18:30:15 2010 From: perfects at post.comunit.de (Minster Dermady) Date: Mon, 20 Sep 2010 19:30:15 +0100 Subject: l grip, grasping them until his Message-ID: <4C97A604.2010604@post.comunit.de> a fine powder. By the time Palmer Billy returned with the dish half-full of water, they had a handful of the powdered stone ready, and he, with much solemnity, as became a sceptic, emptied it into the water, and slowly swished it to and fro, gradually spilling the water, and with it the finer dust of the stone, until only a little wet sand remained in the bottom of the dish. With his head on one side he lifted the dish, tilted over until the sand caught the light at the proper angle; then he slowly revolved the dish in his hands, the three others closely watching the expression of his face. Without a word he put the dish on the ground, and, walking over to Peters, slapped him vigorously on the back. "I'm an old hand," he exclaimed--"old enough in years and mining to -------------- next part -------------- A non-text attachment was scrubbed... Name: agenesis.jpg Type: application/octet-stream Size: 11782 bytes Desc: not available URL: From oleg at redhat.com Mon Sep 20 19:42:19 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 20 Sep 2010 21:42:19 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines Message-ID: <20100920194219.GA6135@redhat.com> Test-case: #include #include #include #include #include #include int main(void) { int pid, status; pid = fork(); if (!pid) { assert(ptrace(PTRACE_TRACEME, 0,0,0) == 0); kill(getpid(), SIGSTOP); return 0x23; } assert(wait(&status) == pid); assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); assert(wait(&status) == pid); assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP); assert(ptrace(PTRACE_DETACH, pid, 0,0) == 0); assert(wait(&status) == pid); if (WIFEXITED(status) && WEXITSTATUS(status) == 0x23) return 0; printf("ERR!! exit status: %04x\n", status); return 1; } It fails because TIF_SINGLESTEP is not cleared after PTRACE_DETACH and the tracee gets another trap after resume. Change utrace_reset() to do user_disable_single_step(). Alternatively we could change ptrace layer, but I think this is not ptrace specific. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 1 + 1 file changed, 1 insertion(+) --- kstub/kernel/utrace.c~10_utrace_reset_should_clear_ss 2010-09-20 03:55:12.000000000 +0200 +++ kstub/kernel/utrace.c 2010-09-20 21:33:47.000000000 +0200 @@ -709,6 +709,7 @@ static bool utrace_reset(struct task_str */ utrace->resume = UTRACE_RESUME; utrace->signal_handler = 0; + user_disable_single_step(task); } /* From jan.kratochvil at redhat.com Mon Sep 20 20:08:13 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 20 Sep 2010 22:08:13 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100920194219.GA6135@redhat.com> References: <20100920194219.GA6135@redhat.com> Message-ID: <20100920200813.GA22677@host1.dyn.jankratochvil.net> On Mon, 20 Sep 2010 21:42:19 +0200, Oleg Nesterov wrote: > Test-case: Checked in http://sourceware.org/systemtap/wiki/utrace/tests as "step-detach". Thanks, Jan From premier_02 at masteremarketing.com.br Mon Sep 20 13:49:41 2010 From: premier_02 at masteremarketing.com.br (Premier Training) Date: Mon, 20 Sep 2010 09:49:41 -0400 Subject: =?UTF-8?B?R2VzdMOjbyBkZSBGbHV4byBkZSBjYWl4YQ==?= Message-ID: <0d516f409da941783462948c1af9ad57@vailaemail.com.br> An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Sep 21 08:49:16 2010 From: roland at redhat.com (Roland McGrath) Date: Tue, 21 Sep 2010 01:49:16 -0700 (PDT) Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: Oleg Nesterov's message of Monday, 20 September 2010 21:42:19 +0200 <20100920194219.GA6135@redhat.com> References: <20100920194219.GA6135@redhat.com> Message-ID: <20100921084916.CCAA34062D@magilla.sf.frob.com> > Change utrace_reset() to do user_disable_single_step(). Alternatively > we could change ptrace layer, but I think this is not ptrace specific. Yes, it's right to fix this in the utrace layer. But I'm not sure that's the right place in the code to fix it. The expectation is that either we'll get to finish_resume_report, which calls user_*_step, or that utrace_control is resuming us without any expectation of a report. For UTRACE_RESUME in that case, utrace_control calls user_disable_single_step. So probably the UTRACE_DETACH case there should just do it to. Thanks, Roland From envoi at drp55.com Tue Sep 21 09:11:29 2010 From: envoi at drp55.com (DHL Epost) Date: Tue, 21 Sep 2010 12:11:29 +0300 Subject: Envoyez votre courrier depuis votre ordinateur Message-ID: <409f4645ec83480c8c0f4f689b14038e@m1.newmarket05.in> An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Sep 21 23:52:38 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Sep 2010 01:52:38 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100921084916.CCAA34062D@magilla.sf.frob.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> Message-ID: <20100921235238.GA18399@redhat.com> On 09/21, Roland McGrath wrote: > > > Change utrace_reset() to do user_disable_single_step(). Alternatively > > we could change ptrace layer, but I think this is not ptrace specific. > > Yes, it's right to fix this in the utrace layer. > But I'm not sure that's the right place in the code to fix it. > > The expectation is that either we'll get to finish_resume_report, > which calls user_*_step, or that utrace_control is resuming us > without any expectation of a report. For UTRACE_RESUME in that > case, utrace_control calls user_disable_single_step. So probably > the UTRACE_DETACH case there should just do it to. Yes, initially I was going to change utrace_control(DETACH), and this certainly looks more clean. I was worried about the case when the TIF_SINGLESTEP tracee detaches itself and escapes finish_resume_report()->user_disable_single_step(), say, utrace_report_exec(). But probably we can ignore this. Another concern was implicit detach, but thinking more I do not see why utrace_resume() is better. OK, I'll do some testing and resend right now. In UTRACE_DETACH case reset can be true but the tracee is running. But I don't think it makes sense to check target->exit_state == 0, correct? Oleg. From roland at redhat.com Wed Sep 22 00:08:34 2010 From: roland at redhat.com (Roland McGrath) Date: Tue, 21 Sep 2010 17:08:34 -0700 (PDT) Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: Oleg Nesterov's message of Wednesday, 22 September 2010 01:52:38 +0200 <20100921235238.GA18399@redhat.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> Message-ID: <20100922000834.A953740614@magilla.sf.frob.com> > I was worried about the case when the TIF_SINGLESTEP tracee detaches > itself and escapes finish_resume_report()->user_disable_single_step(), > say, utrace_report_exec(). But probably we can ignore this. No, I think that is indeed a problem. If no engine is still attached whose last callback returned UTRACE_SINGLESTEP, we should never return to user mode with single-step enabled. > Another concern was implicit detach, but thinking more I do not see > why utrace_resume() is better. > > OK, I'll do some testing and resend right now. In UTRACE_DETACH case > reset can be true but the tracee is running. But I don't think it > makes sense to check target->exit_state == 0, correct? I think it's OK if it's running with ->exit_state set (or even with just PF_EXITING set), i.e. already in kernel mode and never going back to user mode. (Then it's essentially equivalent to calling user_*_step while racing with a SIGKILL death, which has to be OK.) Any other kind of running would not be OK. Thanks, Roland From oleg at redhat.com Wed Sep 22 00:13:23 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Sep 2010 02:13:23 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100922000834.A953740614@magilla.sf.frob.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> Message-ID: <20100922001323.GA21756@redhat.com> On 09/21, Roland McGrath wrote: > > > I was worried about the case when the TIF_SINGLESTEP tracee detaches > > itself and escapes finish_resume_report()->user_disable_single_step(), > > say, utrace_report_exec(). But probably we can ignore this. > > No, I think that is indeed a problem. If no engine is still attached > whose last callback returned UTRACE_SINGLESTEP, we should never return > to user mode with single-step enabled. OK, so what should we do for now? Without the multitracing utrace_resume()->user_disable_single_step() fixes the problem. Otherwise we probably need ENGINE_WANTS_SINGLESTEP. > > Another concern was implicit detach, but thinking more I do not see > > why utrace_resume() is better. > > > > OK, I'll do some testing and resend right now. In UTRACE_DETACH case > > reset can be true but the tracee is running. But I don't think it > > makes sense to check target->exit_state == 0, correct? > > I think it's OK if it's running with ->exit_state set (or even with just > PF_EXITING set), i.e. already in kernel mode and never going back to > user mode. (Then it's essentially equivalent to calling user_*_step > while racing with a SIGKILL death, which has to be OK.) Any other kind > of running would not be OK. Yes, my concern was "running and !current", not "exiting". This is OK on x86 but user_disable_single_step() is arch specific. Oleg. From oleg at redhat.com Wed Sep 22 00:26:01 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Sep 2010 02:26:01 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100922001323.GA21756@redhat.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> Message-ID: <20100922002601.GA22246@redhat.com> On 09/22, Oleg Nesterov wrote: > > On 09/21, Roland McGrath wrote: > > > > > I was worried about the case when the TIF_SINGLESTEP tracee detaches > > > itself and escapes finish_resume_report()->user_disable_single_step(), > > > say, utrace_report_exec(). But probably we can ignore this. > > > > No, I think that is indeed a problem. If no engine is still attached > > whose last callback returned UTRACE_SINGLESTEP, we should never return > > to user mode with single-step enabled. > > OK, so what should we do for now? > > Without the multitracing utrace_resume()->user_disable_single_step() > fixes the problem. Otherwise we probably need ENGINE_WANTS_SINGLESTEP. As expected, the patch below equally fixes the problem and passes ptrace-tests. Which one do you prefer? Note that, since we are going to change UTRACE_RESUME to remove ENGINE_STOP from utrace_flags, we can probably unify DETACH/RESUME case UTRACE_DETACH: mark_engine_detached(engine); reset = reset || utrace_do_stop(target, utrace); if (!reset) { /* * As in utrace_set_events(), this barrier ensures * that our engine->flags changes have hit before we * examine utrace->reporting, pairing with the barrier * in start_callback(). If @target has not yet hit * finish_callback() to clear utrace->reporting, we * might be in the middle of a callback to @engine. */ smp_mb(); if (utrace->reporting == engine) ret = -EINPROGRESS; } /* fall */ case UTRACE_RESUME: clear_engine_wants_stop(engine); target->utrace_flags &= ~ENGINE_STOP; /* * This and all other cases imply resuming if stopped. * There might not be another report before it just * resumes, so make sure single-step is not left set. */ if (likely(reset)) user_disable_single_step(target); break; --- kstub/kernel/utrace.c~10_utrace_reset_should_clear_ss 2010-09-20 03:55:12.000000000 +0200 +++ kstub/kernel/utrace.c 2010-09-22 01:54:24.000000000 +0200 @@ -1139,7 +1139,9 @@ int utrace_control(struct task_struct *t target->utrace_flags &= ~ENGINE_STOP; mark_engine_detached(engine); reset = reset || utrace_do_stop(target, utrace); - if (!reset) { + if (reset) { + user_disable_single_step(target); + } else { /* * As in utrace_set_events(), this barrier ensures * that our engine->flags changes have hit before we From roland at redhat.com Wed Sep 22 02:16:21 2010 From: roland at redhat.com (Roland McGrath) Date: Tue, 21 Sep 2010 19:16:21 -0700 (PDT) Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: Oleg Nesterov's message of Wednesday, 22 September 2010 02:13:23 +0200 <20100922001323.GA21756@redhat.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> Message-ID: <20100922021621.3D07540614@magilla.sf.frob.com> > OK, so what should we do for now? If we can't come to a straightforward answer for the general case fairly quickly, then we can do the simple change to start with. > Without the multitracing utrace_resume()->user_disable_single_step() > fixes the problem. Otherwise we probably need ENGINE_WANTS_SINGLESTEP. No, no, we don't want that. We don't need more state. And, remember, we really don't need to microoptimize cases when single-step was used recently--the cost of taking one more single-step trap and percolating through the signal paths was going to be pretty large anyway. It's better to have a spurious report (preferably just spurious TIF_NOTIFY_RESUME with no actual callbacks) following any detach, or whatever it takes to ensure user_disable_single_step() always runs if user_enable_*_step did before and there is no engine around to see a report_quiesce callback pass. If there is a report_quiesce or report_signal callback pass where nobody returns UTRACE_*STEP, then we should never leave stepping enabled when we return to user mode. > Yes, my concern was "running and !current", not "exiting". This is OK on > x86 but user_disable_single_step() is arch specific. It's not really OK on x86 either, with either SMP or preemption. Thanks, Roland From oleg at redhat.com Wed Sep 22 02:22:26 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Sep 2010 04:22:26 +0200 Subject: gdbstub initial code, v11 Message-ID: <20100922022226.GA27400@redhat.com> Changes: syscall stepping + minor cleanups. Seems to work, more or less, but surely there are some bugs. Honestly, I don't really know how do the "right thing" here. Anyway, most probably this code will be changed. Like ptrace, ugdb uses ->report_syscall_exit() to synthesize a trap. Unlike ptrace, ugdb_report_signal() doesn't send SIGTRAP to itself but reports SIGTRAP using siginfo_t we have. In any case, whatever we do, multiple tracers can confuse each other. Next: fully implement g/G/p/P, currently I am a bit confused... But what about features? What should I do next? all-stop, thread-specific breakpoints (currently I have no idea what this means), or what? Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1024 #define PACKET_SIZE 1024 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; bool t_step; // XXX: move me into t_stop_event siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all, bool step) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { unsigned long events = 0; enum utrace_resume_action action = UTRACE_RESUME; thread->t_step = step; if (step) { /* to correctly step over syscall insn */ events |= UTRACE_EVENT(SYSCALL_EXIT); action = UTRACE_SINGLESTEP; } // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, events); ugdb_control(thread, action); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; if (thread->t_step) { WARN_ON(orig_ka); // user_single_step_siginfo(current, regs, info); memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; break; } /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (!thread->t_siginfo) { /* UTRACE_INTERRUPT from ugdb_report_syscall_exit() */ if (thread->t_step) { WARN_ON(orig_ka); // user_single_step_siginfo(current, regs, info); memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; break; } } else { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); if (thread->t_step) return UTRACE_SINGLESTEP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static u32 ugdb_report_syscall_exit(u32 action, struct utrace_engine *engine, struct pt_regs *regs) { struct ugdb_thread *thread = engine->data; if (thread->t_step) return UTRACE_INTERRUPT; printk(KERN_INFO "ugdb: unexpected SYSCALL_EXIT\n"); return action; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_syscall_exit = ugdb_report_syscall_exit, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL, false); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; bool step; step = (*cmd == 'S' || *cmd == 's'); switch (*cmd++) { case 'C': case 'S': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': case 's': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; /* * Otherwise I do not know what to do if sig/step, and anyway * I don't think gdb can try to cont a thread which was not * reported as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false, step) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static const char *handle_setregs(struct ugdb *ugdb, char *cmd) { printk(KERN_INFO "ugdb: unexpected $G packet.\n"); return ""; } static const char *handle_set_one_reg(struct ugdb *ugdb, char *cmd) { unsigned int reg; long val; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "%x=%lx", ®, &val) != 2) goto err; if (reg != 0x10 && reg != 0x39) { printk(KERN_INFO "ugdb: unknown reg %x\n", reg); goto err; } // XXX: Hmm. val = be64_to_cpu(val); // DO NOT LOOK AT THIS TEMPORARY CODE task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; if (reg == 0x10) task_pt_regs(task)->ip = val; else if (reg == 0x39) task_pt_regs(task)->orig_ax = val; ugdb_finish_examine(ugdb, &exam); return "OK"; err: return "E01"; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } // XXX: hex_to_bin() after 90378889 commit #include static int cap_hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; hi = cap_hex_to_bin(*cmd++); lo = cap_hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': rc = handle_getregs(ugdb); break; case 'G': rc = handle_setregs(ugdb, cmd + 1); break; case 'P': rc = handle_set_one_reg(ugdb, cmd + 1); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': case 'S': case 's': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit); From sweepers at sscampbell.com Wed Sep 22 02:42:35 2010 From: sweepers at sscampbell.com (Plyler Zimba) Date: Wed, 22 Sep 2010 07:12:35 +0430 Subject: d was g Message-ID: <4C998DF5.6060407@sscampbell.com> Big bowlful! I'm afraid you gave me all the milk,' said Tilly, smiling over the nice, steaming supper that stood ready for her. 'I've had plenty, dear. Sit down and dry your wet feet, and put the bird in my basket on this warm flannel.' Tilly peeped into the closet and saw nothing there but dry bread. 'Mother's given me all the milk, and is going without her tea, 'cause she knows I'm hungry. Now I'll surprise her, and she shall have a good supper too. She is going to split wood, and I'll fix it while she's gone.' So Tilly put down the old tea-pot, carefully poured out a part of the milk, and from her pocket produced a great, plummy bun, that one of the school-children had given her, and she had saved for her mother. A slice of the dry bread was nicely toasted, and the bit of butter set by for her put on it. When her mother came in there was the table drawn up in a -------------- next part -------------- A non-text attachment was scrubbed... Name: vacillates.jpg Type: application/octet-stream Size: 11691 bytes Desc: not available URL: From conscript at omegin.de Wed Sep 22 16:25:19 2010 From: conscript at omegin.de (Dipiano Tofte) Date: Wed, 22 Sep 2010 18:25:19 +0200 Subject: Salt, and pepper. Carley might not have been present Message-ID: <4C9A2C9A.2020708@omegin.de> Nn can fight like the devil?" asked Flo. "No, I don't. But I remember he used to be athletic. Flo, you make me nervous. Did Glenn fight?" "I reckon he did," drawled Flo. "With whom?" "Nobody else but that big hombre, Haze Ruff." "Oh!" gasped Carley, with a violent start. "That--that ruffian! Flo, did you see--were you there?" "I shore was, an' next to a horse race I like a fight," r -------------- next part -------------- A non-text attachment was scrubbed... Name: dockyard.jpg Type: application/octet-stream Size: 11378 bytes Desc: not available URL: From tromey at redhat.com Wed Sep 22 19:09:12 2010 From: tromey at redhat.com (Tom Tromey) Date: Wed, 22 Sep 2010 13:09:12 -0600 Subject: gdbstub initial code, v11 In-Reply-To: <20100922022226.GA27400@redhat.com> (Oleg Nesterov's message of "Wed, 22 Sep 2010 04:22:26 +0200") References: <20100922022226.GA27400@redhat.com> Message-ID: Oleg> But what about features? What should I do next? all-stop, Oleg> thread-specific breakpoints (currently I have no idea what Oleg> this means), or what? I think it would be good to implement a feature that shows how this approach is an improvement over the current state of gdb+ptrace or gdb+gdbserver. Exactly what feature this should be... I don't know :-) I would imagine something performance-related. There was previously some discussion about some watchpoint-related thing, I forget the details of that. I don't think thread-specific breakpoints are exposed outside of gdb yet. If that is true, then implementing that would mean adding remote protocol features and also other stuff inside gdb. So, I would suggest not tackling this yet. Tom From jan.kratochvil at redhat.com Wed Sep 22 19:18:37 2010 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 22 Sep 2010 21:18:37 +0200 Subject: gdbstub initial code, v11 In-Reply-To: References: <20100922022226.GA27400@redhat.com> Message-ID: <20100922191837.GA25002@host1.dyn.jankratochvil.net> On Wed, 22 Sep 2010 21:09:12 +0200, Tom Tromey wrote: > I think it would be good to implement a feature that shows how this > approach is an improvement over the current state of gdb+ptrace or > gdb+gdbserver. > > Exactly what feature this should be... I don't know :-) > I would imagine something performance-related. I would bet on a massive threads creating/deleting testcase signalling tasks around, together with watchpoints. There are races in the linux-nat code and IIRC even gdbserver code. OTOH if one tries hard one can probably manage one day to fix all the corner cases in the ptrace based linux-nat and gdbserver. Regards, Jan From fche at redhat.com Wed Sep 22 22:06:05 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Wed, 22 Sep 2010 18:06:05 -0400 Subject: gdbstub initial code, v11 In-Reply-To: <20100922022226.GA27400@redhat.com> (Oleg Nesterov's message of "Wed, 22 Sep 2010 04:22:26 +0200") References: <20100922022226.GA27400@redhat.com> Message-ID: oleg wrote: > [...] Honestly, I don't really know how do the "right thing" here. > Anyway, most probably this code will be changed. Like ptrace, ugdb > uses ->report_syscall_exit() to synthesize a trap. Unlike ptrace, > ugdb_report_signal() doesn't send SIGTRAP to itself but reports > SIGTRAP using siginfo_t we have. In any case, whatever we do, > multiple tracers can confuse each other. (It seems to me that a pure gdb report, without a synthetic self-injected SIGTRAP, should be fine.) > Next: fully implement g/G/p/P, currently I am a bit confused... > But what about features? [...] You could dig out the old "fishing plan". One demonstrated improvement was from simulating (software) watchpoints within the gdb stub, instead of having gdb fall back to issing countless single-steps with memory-fetch inquiries in between. - FChE From oleg at redhat.com Wed Sep 22 23:14:51 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Sep 2010 01:14:51 +0200 Subject: gdbstub initial code, v11 In-Reply-To: References: <20100922022226.GA27400@redhat.com> Message-ID: <20100922231451.GA11198@redhat.com> On 09/22, Frank Ch. Eigler wrote: > > oleg wrote: > > > [...] Honestly, I don't really know how do the "right thing" here. > > Anyway, most probably this code will be changed. Like ptrace, ugdb > > uses ->report_syscall_exit() to synthesize a trap. Unlike ptrace, > > ugdb_report_signal() doesn't send SIGTRAP to itself but reports > > SIGTRAP using siginfo_t we have. In any case, whatever we do, > > multiple tracers can confuse each other. > > (It seems to me that a pure gdb report, without a synthetic > self-injected SIGTRAP, should be fine.) What do you mean? > > Next: fully implement g/G/p/P, currently I am a bit confused... > > But what about features? [...] > > You could dig out the old "fishing plan". One demonstrated > improvement was from simulating (software) watchpoints within the > gdb stub, instead of having gdb fall back to issing countless > single-steps with memory-fetch inquiries in between. When I do 'watch', gdb sends '$Z2'. I am a bit confused, iirc it was decided I shouldn't play with Z packets now. But I won't argue. Oleg. From fche at redhat.com Wed Sep 22 23:39:09 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Wed, 22 Sep 2010 19:39:09 -0400 Subject: gdbstub initial code, v11 In-Reply-To: <20100922231451.GA11198@redhat.com> References: <20100922022226.GA27400@redhat.com> <20100922231451.GA11198@redhat.com> Message-ID: <20100922233909.GF2727@redhat.com> Hi - On Thu, Sep 23, 2010 at 01:14:51AM +0200, Oleg Nesterov wrote: > > (It seems to me that a pure gdb report, without a synthetic > > self-injected SIGTRAP, should be fine.) > > What do you mean? (Never mind, I'm probably just confused about what you were asking.) > > > Next: fully implement g/G/p/P, currently I am a bit confused... > > > But what about features? [...] > > > > You could dig out the old "fishing plan". One demonstrated > > improvement was from simulating (software) watchpoints within the > > gdb stub, instead of having gdb fall back to issing countless > > single-steps with memory-fetch inquiries in between. > > When I do 'watch', gdb sends '$Z2'. I am a bit confused, iirc it > was decided I shouldn't play with Z packets now. But I won't > argue. There are Z packets and then there are Z packets. The ones Roland told you not to worry about are Z0/Z1 related to (code) breakpoints, which should be implemented via uprobes at some point. The ones I'm talking about are Z2/Z3 for (data) watchpoints. - FChE From oleg at redhat.com Wed Sep 22 23:44:43 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Sep 2010 01:44:43 +0200 Subject: gdbstub initial code, v11 In-Reply-To: <20100922233909.GF2727@redhat.com> References: <20100922022226.GA27400@redhat.com> <20100922231451.GA11198@redhat.com> <20100922233909.GF2727@redhat.com> Message-ID: <20100922234442.GA13379@redhat.com> On 09/22, Frank Ch. Eigler wrote: > > On Thu, Sep 23, 2010 at 01:14:51AM +0200, Oleg Nesterov wrote: > > > > When I do 'watch', gdb sends '$Z2'. I am a bit confused, iirc it > > was decided I shouldn't play with Z packets now. But I won't > > argue. > > There are Z packets and then there are Z packets. The ones Roland > told you not to worry about are Z0/Z1 related to (code) breakpoints, > which should be implemented via uprobes at some point. > > The ones I'm talking about are Z2/Z3 for (data) watchpoints. Ah, OK, thanks. I'll try to understand how this works. Oleg. From news at news.streetmarketing.com.pt Wed Sep 22 21:45:02 2010 From: news at news.streetmarketing.com.pt (=?windows-1252?Q?Drive_&_Cash_-NEWS?=) Date: Wed, 22 Sep 2010 22:45:02 +0100 Subject: Pagamos para que conduza o seu carro. Message-ID: <499825d82554200a4924a66c00165600@news.streetmarketing.com.pt> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Sep 23 03:16:27 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Sep 2010 05:16:27 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100922021621.3D07540614@magilla.sf.frob.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> <20100922021621.3D07540614@magilla.sf.frob.com> Message-ID: <20100923031627.GA21626@redhat.com> On 09/21, Roland McGrath wrote: > > > OK, so what should we do for now? > > If we can't come to a straightforward answer for the general case > fairly quickly, then we can do the simple change to start with. I think we should start with changing utrace_control(DETACH) anyway, then try to improve. I'll ressend the one-liner I already showed. > > Without the multitracing utrace_resume()->user_disable_single_step() > > fixes the problem. Otherwise we probably need ENGINE_WANTS_SINGLESTEP. > > No, no, we don't want that. We don't need more state. And, remember, > we really don't need to microoptimize cases when single-step was used > recently--the cost of taking one more single-step trap and percolating > through the signal paths was going to be pretty large anyway. OK, > It's better to have a spurious report (preferably just spurious > TIF_NOTIFY_RESUME with no actual callbacks) following any detach, > or whatever it takes to ensure user_disable_single_step() always > runs if user_enable_*_step did before and there is no engine around > to see a report_quiesce callback pass. If there is a report_quiesce > or report_signal callback pass where nobody returns UTRACE_*STEP, > then we should never leave stepping enabled when we return to user mode. Hmm. I'll try to think more. Right now I don't really understand how to do this correctly. OK, finish_callback_report() and utrace_control(DETACH) can set TIF_NOTIFY_RESUME. But what if there are no more attached engines? Looks like, utrace_resume(UTRACE_RESUME) needs to handle this special case. And utrace_reset() shouldn't clear task->utrace_flags, otherwise utrace_resume/utrace_get_signal won't be called. So, probably detach should set TIF_NOTIFY_RESUME, but utrace_reset() should do user_disable_single_step() too if no more engines. Confused. And in fact I don't understand why this is important. When it comes to multiracing, any engine can hit the unwanted/unexpected trap because another engine can ask for UTRACE_*STEP. The only really important (I think) case is when the last engine detaches. IOW. Suppose that eninge E does utrace_control(STEP) or its callback returns UTRACE_*STEP. If we do not detach this engine, other engines will see the trap. So why it is so important to clear X86_EFLAGS_TF if we detach E ? Oleg. From oleg at redhat.com Thu Sep 23 03:20:33 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Sep 2010 05:20:33 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100923031627.GA21626@redhat.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> <20100922021621.3D07540614@magilla.sf.frob.com> <20100923031627.GA21626@redhat.com> Message-ID: <20100923032033.GB21626@redhat.com> On 09/23, Oleg Nesterov wrote: > > On 09/21, Roland McGrath wrote: > > > > It's better to have a spurious report (preferably just spurious > > TIF_NOTIFY_RESUME with no actual callbacks) following any detach, > > or whatever it takes to ensure user_disable_single_step() always > > runs if user_enable_*_step did before and there is no engine around > > to see a report_quiesce callback pass. If there is a report_quiesce > > or report_signal callback pass where nobody returns UTRACE_*STEP, > > then we should never leave stepping enabled when we return to user mode. > > Hmm. I'll try to think more. Right now I don't really understand > how to do this correctly. > > OK, finish_callback_report() and utrace_control(DETACH) can set > TIF_NOTIFY_RESUME. But what if there are no more attached engines? > Looks like, utrace_resume(UTRACE_RESUME) needs to handle this special > case. And utrace_reset() shouldn't clear task->utrace_flags, otherwise > utrace_resume/utrace_get_signal won't be called. > > So, probably detach should set TIF_NOTIFY_RESUME, but utrace_reset() > should do user_disable_single_step() too if no more engines. Confused. Or, detach can always do user_disable_single_step() and set TIF_NOTIFY_RESUME. If another engine wants stepping its report_quiesce() should re-ack UTRACE_SINGLESTEP anyway, otherwise it is buggy. > And in fact I don't understand why this is important. When it comes > to multiracing, any engine can hit the unwanted/unexpected trap > because another engine can ask for UTRACE_*STEP. The only really > important (I think) case is when the last engine detaches. Aaah. please ignore. Somehow I assumed every engine should hook SIGTRAP. Oleg. From roland at redhat.com Thu Sep 23 21:21:38 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 23 Sep 2010 14:21:38 -0700 (PDT) Subject: gdbstub initial code, v11 In-Reply-To: Oleg Nesterov's message of Thursday, 23 September 2010 01:44:43 +0200 <20100922234442.GA13379@redhat.com> References: <20100922022226.GA27400@redhat.com> <20100922231451.GA11198@redhat.com> <20100922233909.GF2727@redhat.com> <20100922234442.GA13379@redhat.com> Message-ID: <20100923212138.5B3E940048@magilla.sf.frob.com> > > The ones I'm talking about are Z2/Z3 for (data) watchpoints. > > Ah, OK, thanks. I'll try to understand how this works. In theory these will map to uses of the hw_breakpoint interface. Thanks, Roland From roland at redhat.com Thu Sep 23 21:24:23 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 23 Sep 2010 14:24:23 -0700 (PDT) Subject: gdbstub initial code, v11 In-Reply-To: Tom Tromey's message of Wednesday, 22 September 2010 13:09:12 -0600 References: <20100922022226.GA27400@redhat.com> Message-ID: <20100923212423.B4EF540048@magilla.sf.frob.com> > I think it would be good to implement a feature that shows how this > approach is an improvement over the current state of gdb+ptrace or > gdb+gdbserver. > > Exactly what feature this should be... I don't know :-) > I would imagine something performance-related. My vague notion was that we'd get it working well enough to have basic parity with native or gdbserver on some realish test cases, and then just look at the protocol interaction log to see cases where we could reduce round-trips between gdb and the stub. Some of those are bound to entail protocol extensions and gdb changes to exploit them. Off hand, the Z cases might be the only things that won't need that. Thanks, Roland From fche at redhat.com Thu Sep 23 21:29:57 2010 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 23 Sep 2010 17:29:57 -0400 Subject: gdbstub initial code, v11 In-Reply-To: <20100923212138.5B3E940048@magilla.sf.frob.com> References: <20100922022226.GA27400@redhat.com> <20100922231451.GA11198@redhat.com> <20100922233909.GF2727@redhat.com> <20100922234442.GA13379@redhat.com> <20100923212138.5B3E940048@magilla.sf.frob.com> Message-ID: <20100923212957.GC23722@redhat.com> Hi - On Thu, Sep 23, 2010 at 02:21:38PM -0700, Roland McGrath wrote: > > > The ones I'm talking about are Z2/Z3 for (data) watchpoints. > > Ah, OK, thanks. I'll try to understand how this works. > > In theory these will map to uses of the hw_breakpoint interface. Not quite. The hw_breakpoint widget is only useful for the first few active watchpoints. The rest, which gdb calls software watchpoints, can be implemented in ugdb by local singlestep + polling, without gdb's live involvement. - FChE From roland at redhat.com Thu Sep 23 22:30:20 2010 From: roland at redhat.com (Roland McGrath) Date: Thu, 23 Sep 2010 15:30:20 -0700 (PDT) Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: Oleg Nesterov's message of Thursday, 23 September 2010 05:16:27 +0200 <20100923031627.GA21626@redhat.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> <20100922021621.3D07540614@magilla.sf.frob.com> <20100923031627.GA21626@redhat.com> Message-ID: <20100923223020.B3CEC40049@magilla.sf.frob.com> > I think we should start with changing utrace_control(DETACH) anyway, > then try to improve. I'll ressend the one-liner I already showed. Ok. > Hmm. I'll try to think more. Right now I don't really understand > how to do this correctly. I wasn't immediately sure either. > OK, finish_callback_report() and utrace_control(DETACH) can set > TIF_NOTIFY_RESUME. Right. Those utrace_resume has the report.action==UTRACE_RESUME bail-out case. So either that would change or detach would also do UTRACE_REPORT. > But what if there are no more attached engines? > Looks like, utrace_resume(UTRACE_RESUME) needs to handle this special > case. And utrace_reset() shouldn't clear task->utrace_flags, otherwise > utrace_resume/utrace_get_signal won't be called. Right. Or else tracehook_notify_resume could call utrace_resume unconditionally, but I'm not at all sure that is not worse. The original theory was that it should always be OK to have some utrace_flags bits stay set when they are "stale", because any kind of reporting pass that got enabled would hit the report->spurious case and clean the state up synchronously when it's safe. > So, probably detach should set TIF_NOTIFY_RESUME, but utrace_reset() > should do user_disable_single_step() too if no more engines. Confused. If there are no more engines but the tracee is still running, we still shouldn't do it there because it still might not be entirely safe. If the tracee is not stopped, it's only safe to call in current. > And in fact I don't understand why this is important. When it comes > to multiracing, any engine can hit the unwanted/unexpected trap > because another engine can ask for UTRACE_*STEP. Right. An engine earlier in the list could swallow the signal so the next engines' callbacks didn't see it. But it doesn't know that some later engines didn't also ask for stepping. So there would have to be some understood convention between engines. For example, a later engine could see info->si_signo==SIGTRAP et al and act on that even when the incoming utrace_signal_action(action)==UTRACE_SIGNAL_IGN. Of course, that doesn't help a non-stepping engine that is earlier in the list to know that a later engine will be swallowing the signal. The original theory on this was that we'd one day stop overloading user signals for debugger-induced traps. In some past TODO lists and postings I referred to "extension events". The idea (in part) was that things like hardware stepping would generate a special new flavor of utrace event rather than a real signal that has to be intercepted. Then engines' callbacks would easily see that this was a debugging event induced by some engine and ignore it (or more likely, just never get any callback unless your engine registered interest in stepping). This would also address the case of asynchronous engine detach just after a trap has actually hit, where today the SIGTRAP is queued and then later won't be intercepted by a debugger, and instead kills the user process. But we don't have any of that now, and don't yet know if we will really pursue any big improvements at this API level. > The only really > important (I think) case is when the last engine detaches. That's the most important case, sure. But in any case that is not actually racy, we should avoid later spurious traps. > IOW. Suppose that eninge E does utrace_control(STEP) or its callback > returns UTRACE_*STEP. If we do not detach this engine, other engines > will see the trap. That's only so if the tracee actually gets back to user mode before we have another reporting pass. > So why it is so important to clear X86_EFLAGS_TF if we detach E ? Perhaps I am worrying too much about it. The worst thing is if it could really get "stuck". But that shouldn't be possible if there are any engines at all, perhaps only any with UTRACE_EVENT(QUIESCE) set. Worst case, one spurious SIGTRAP will get to a report_signal pass, but nobody will return UTRACE_*STEP again, so there won't be another. (Of course, nobody will swallow that SIGTRAP and so it will terminate the process first anyway, but that's another problem.) What seems important is any "non-racy" scenarios. That is, where perhaps it wasn't properly stopped and E detached "asynchronously", but in practice the tracee was known to be otherwise blocked elsewhere or something, so the detach should have full effect before it returns to user mode. But that is just vague theory off hand. Thanks, Roland From mldireto at tudoemoferta.com.br Fri Sep 24 06:48:19 2010 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Fri, 24 Sep 2010 03:48:19 -0300 Subject: Primavera. Curta a sua com nossas ofertas! Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Sun Sep 26 15:48:39 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 26 Sep 2010 17:48:39 +0200 Subject: [PATCH] utrace: utrace_reset() should clear TIF_SINGLESTEP if no more engines In-Reply-To: <20100923223020.B3CEC40049@magilla.sf.frob.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> <20100922021621.3D07540614@magilla.sf.frob.com> <20100923031627.GA21626@redhat.com> <20100923223020.B3CEC40049@magilla.sf.frob.com> Message-ID: <20100926154839.GA20803@redhat.com> On 09/23, Roland McGrath wrote: > > > I think we should start with changing utrace_control(DETACH) anyway, > > then try to improve. I'll ressend the one-liner I already showed. > > Ok. Yes. I think we need a simple fix first, please see another email I am going to send. However, I am a bit confused. I was going to send the patch which changes utrace_control(DETACH) as you suggested, but now I am not sure. See below. > The original theory on this was that we'd one day stop overloading > user signals for debugger-induced traps. > things like hardware stepping would generate a special new flavor > of utrace event > > But we don't have any of that now, and don't yet know if we will > really pursue any big improvements at this API level. Yes! I thought about this too many times. So. Let's discuss the alternatives for now. The 1st patch I sent initially: --- kstub/kernel/utrace.c~10_utrace_reset_should_clear_ss 2010-09-20 03:55:12.000000000 +0200 +++ kstub/kernel/utrace.c 2010-09-20 21:33:47.000000000 +0200 @@ -709,6 +709,7 @@ static bool utrace_reset(struct task_str */ utrace->resume = UTRACE_RESUME; utrace->signal_handler = 0; + user_disable_single_step(task); } /* It clears TIF_SINGLESTEP when the last engine detaches. The 2nd one which changes utrace_control(DETACH), @@ -1139,7 +1139,9 @@ int utrace_control(struct task_struct *t target->utrace_flags &= ~ENGINE_STOP; mark_engine_detached(engine); reset = reset || utrace_do_stop(target, utrace); - if (!reset) { + if (reset) { + user_disable_single_step(target); + } else { /* * As in utrace_set_events(), this barrier ensures * that our engine->flags changes have hit before we It doesn't cover the case when the TIF_SINGLESTEP tracee detaches itself, but a) currently the are no such engines, and b) it looks more clean. However, I am starting to think that if you prefer this change we have a better option. Instead of duplicating UTRACE_RESUME logic, perhaps the patch below makes more sense? Please tell me which fix you prefer? Or just commit the fix you like more. Oleg. --- x/kernel/utrace.c +++ x/kernel/utrace.c @@ -716,8 +716,15 @@ static bool utrace_reset(struct task_str /* * If no more engines want it stopped, wake it up. */ - if (task_is_traced(task) && !(flags & ENGINE_STOP)) + if (task_is_traced(task) && !(flags & ENGINE_STOP)) { + /* + * It just resumes, so make sure single-step + * is not left set. + */ + if (utrace->resume == UTRACE_RESUME) + user_disable_single_step(task); utrace_wakeup(task, utrace); + } /* * In theory spin_lock() doesn't imply rcu_read_lock(). @@ -1157,14 +1164,7 @@ int utrace_control(struct task_struct *t break; case UTRACE_RESUME: - /* - * This and all other cases imply resuming if stopped. - * There might not be another report before it just - * resumes, so make sure single-step is not left set. - */ clear_engine_wants_stop(engine); - if (likely(reset)) - user_disable_single_step(target); break; case UTRACE_BLOCKSTEP: From oleg at redhat.com Sun Sep 26 16:01:03 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 26 Sep 2010 18:01:03 +0200 Subject: utrace && unwanted traps In-Reply-To: <20100923223020.B3CEC40049@magilla.sf.frob.com> References: <20100920194219.GA6135@redhat.com> <20100921084916.CCAA34062D@magilla.sf.frob.com> <20100921235238.GA18399@redhat.com> <20100922000834.A953740614@magilla.sf.frob.com> <20100922001323.GA21756@redhat.com> <20100922021621.3D07540614@magilla.sf.frob.com> <20100923031627.GA21626@redhat.com> <20100923223020.B3CEC40049@magilla.sf.frob.com> Message-ID: <20100926160103.GB20803@redhat.com> On 09/23, Roland McGrath wrote: > > > OK, finish_callback_report() and utrace_control(DETACH) can set > > TIF_NOTIFY_RESUME. > > Right. Those utrace_resume has the report.action==UTRACE_RESUME bail-out > case. So either that would change or detach would also do UTRACE_REPORT. > > > But what if there are no more attached engines? > > Looks like, utrace_resume(UTRACE_RESUME) needs to handle this special > > case. And utrace_reset() shouldn't clear task->utrace_flags, otherwise > > utrace_resume/utrace_get_signal won't be called. > > Right. Or else tracehook_notify_resume could call utrace_resume > unconditionally, but I'm not at all sure that is not worse. The > original theory was that it should always be OK to have some > utrace_flags bits stay set when they are "stale", because any kind of > reporting pass that got enabled would hit the report->spurious case > and clean the state up synchronously when it's safe. I tried to make the patch which addresses this issue, but surprisingly I failed. Because I think there are more (minor) problems here. When it comes to multitracing, we can have the unwanted trap even without detaching. In short: I no longer understand why utrace->resume can be UTRACE_*STEP when the tracee is stopped, and in fact I think this is not right. For example. Consider two engines, E1 and E2. To simplify the discussion suppose that both engines have engine->data->resume and ->report_quiesce() just returns ->resume. So, if the debugger wants, say, single-step, it does engine->data->resume = UTRACE_SINGLESTEP; utrace_control(UTRACE_SINGLESTEP); Actually, any engine should do something like this. Now suppose that E1 wants UTRACE_SINGLESTEP, E2 asks for UTRACE_STOP. In this case utrace_resume() results in utrace_stop() which sets utrace->resume = UTRACE_SINGLESTEP before sleeping. First of all - why? Yes, the theory is that we have another reporting loop after wake_up, but utrace->resume = UTRACE_REPORT is enough, E1 should always acquire UTRACE_SINGLESTEP if needed or it is buggy. But more importantly, this doesn't look right or I missed something. Suppose that, before E2 resumes the tracee, E1 does utrace_control(STOP) which immediately succeeds and allows E1 to play with the stopped tracee. Again, to simplify the discussion, suppose that E2 does UTRACE_RESUME and nothing more after that. Now. E1 wants to resume the tracee too and it does engine->data->resume = UTRACE_RESUME; utrace_control(UTRACE_RESUME); utrace_control(RESUME) correctly clears TIF_SINGLESTEP, but it doesn't change utrace->resume. This means utrace_resume() doesn't do the reporting loop, it just calls user_enable_single_step() and returns to user-mode. So. Could you explain why utrace_stop() should ever keep UTRACE_STEP in utrace->resume? finish_report() does the same but this looks fine. Also. I am not sure utrace_control(UTRACE_STEP) should always set utrace->resume = UTRACE_STEP. If the tracee is stopped but there is another ENGINE_STOP engine (iow, the tracee won't be resumed right now) we have the same problem. Off-topic, #define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) why UTRACE_RESUME_MAX? it should be (ilog2(UTRACE_RESUME_MAX - 1) + 1), no? Oleg. From we at druy.com Mon Sep 27 22:20:09 2010 From: we at druy.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Tue, 28 Sep 2010 06:20:09 +0800 Subject: =?GB2312?B?QjF1dHJhY2UtZGV2ZWzP+srbvqvTorXEvKTA+A==?= Message-ID: <201009272220.o8RMK0Xd007858@mx1.redhat.com> utrace-devel????????2?????????? ???????????????????????????????????????????????????????????????????????????? ??????????2010??10??23-24?? ???? ??????????2010??10??30-31?? ???? ??????????2010??11??6-7?? ???? ??????????2010??11??13-14?? ???? ???????????????????????????????????????????????????????????????????? ??????????2470??/??????2???????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc2010 at 126.com?????? ====================================================================================== ??????????Judge??????????????????????????????????????????????????Harvard???????????????????? Stanford??????????????.????judge??????????????????????????????????????judge???????????????? ?????????????????????????????????????????????????? ?D?D?D?D?D?D???????????????? 1?????????????????????????????????????????????? 2?????????????????????????????????????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????????? 5?????????????????????????????????????????????????????? 6?????????????????????????????????????????? 7?????????????????????????????????????????????????????? 8?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????? ??????????????????????10?????? 1???????????????????????????????????? 2?????????????????????????????? 3???????????????????????????????? 4?????????????????????????????? 5???????????????????????????????? 6???????????????????????????????? 7?????????????????????????????? 8?????????????????????????????????????? 9?????????????????????????????????? 10???????????????????????????????? ??????????????????9?????????? 1?????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????? 2???????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????? 3?????????????????????????? ???????????????????????????????????? 4???????????????????????????? ???????????????????????????????????????????? 5?????????????????????????????????????? ???????????????????????????????????? 6?????????????????????????? ???????????????????????????????????????? 7?????????????????????????????? ?????????????????????????? 8?????????????????????????????????? ?????????????????????????????????????? 9???????????????????????????????????????????? ?????????????????????????????????? ??????????????????????????????????????????? A?????????????????????????? ???????????????????????????????????????? ???????????????????????????????? ?????????????????? B???????????????????????????? 1???????????????????????????? 2?????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????? 7???????????????????????????????????????????????? C???????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ??????????????????????????????! ???????????????????????????? ???????????????????????????? ???????????????????????????????? ??????3???????? ????????????????6?????? ???????????????????????????????????? 1???????????????????? 2???????????????????? 3?????????????????????????? 4?????????????????????? ?????????????????? ??????????????????????9???????? ??????????????????????????5???????? ??????????????????????4???????? ????????????,????????????3??????? ??????????,??????????4??????? ?????????????????????????????????????? ?????????????????????????????? ??????????????????????7?????????????????? ??????????????????????4???????????????????????????? ??????????????????????????3???? ?????????????????????????????????? ???????????????????? 1???????????????? ???????????????????????????????????? ????????????????????4???????? ????????????????6?????? ???????????????????????????????? 2???????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ??????????????6?????????? ?????????????? ???????????????????????? ???????????????????????? ???????????????????????? 1???????????????????????????????????? 2???????????????????????????????????????? 3?????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????? ???????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????? ????????.????????.????????EMBA???????????? 2000??????????????????????????????????????????,???????????????????????????????? ??????????????????????????,??????????????????100?????????????????????????????? ????????????????????????,??????????????????,?????????????????????????????????? ???????????????????????????????????????????????????????????? ---------------------------------------------------------------------------- ??????????2??????????????????????????????????020-62351156?? ??????????????_______________________________________________________ ???????????????? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________????????:_________??????????_________?? ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ????????___________??????????____________??????????_____________ ??????????????????????????????1????????2????????3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From juli_01455 at att.net Mon Sep 27 20:45:52 2010 From: juli_01455 at att.net (juli bello) Date: Mon, 27 Sep 2010 13:45:52 -0700 (PDT) Subject: hellooooooooo Message-ID: <990493.10859.qm@web180614.mail.sp1.yahoo.com> Hi dear hope you are doing just? fine over there my name is Juli i am single seeking for a true love Relationship i just want? to let? you? know? that l come? across your profile from here http://www.heartofasiaonline.com? and after going? through it i found you? interesting, i hope you don,t mind? if? you are interested? to knowing? more about me and? form to send you my picture,? just feel free to contact me at my private mail at (Remember the distance? age? OR color does not matter but? love matters? alot in life? hope to hear from you soon,? have? a nice day and? stay? blessed, i will also like to see your picture yours lovely Juli -------------- next part -------------- An HTML attachment was scrubbed... URL: From envoi at drp55.com Tue Sep 28 07:40:08 2010 From: envoi at drp55.com (Xerox par SoftDirect) Date: Tue, 28 Sep 2010 10:40:08 +0300 Subject: Calculez vos economies Message-ID: An HTML attachment was scrubbed... URL: From rosettaWares at yourfrontrange.com Tue Sep 28 06:51:37 2010 From: rosettaWares at yourfrontrange.com (RosettaStoneOffers) Date: Tue, 28 Sep 2010 06:51:37 +0000 Subject: =?UTF-8?Q?Understand=20Portuguese,Portuguese=20and=20Russian,=20?= =?UTF-8?Q?DownloadyourWares=20at=20RosettaStoneOffers?= Message-ID: <20100928$1069c8ff$1a1ead3$sxm@chinmusic.championshipfans.com> RosettaStoneOffers downloads from yourfrontrange.com for 2010-09-28 10:51:37 utrace-devel, you are cordially invited to a 50 % discount on all of the just released RosettaStoneOffers Language Wares. Travel through all of Europe with your laptop and all of our must-have language and navigation tools. As with all of our titles, you will be able to download the software immediately after purchase. Use your discount code ' Fs0Ol9Hb550Q ' when you get to check out to receive your savings. at yourfrontrange.com we give you offers like no other online store. Start Speaking Spanish Today! Rosetta Stone Spanish Edition Levels 1,2,3 What you Pay? $65(use discount code FO0Ol9D1550U), Your Savings? $435 Details: Rosetta Stone teaches you a new language naturally, by getting you to think, live and breathe the language * Innovative solutions get you speaking new words, right from the start * Rosetta Stone moves forward only when you're ready--you drive the pace, you set the schedule * With Rosetta Stone, you'll discover a foundation of key vocabulary that you'll use to build into a whole new language * Audio Companion lets you take the Rosetta Stone experience anywhere: in the car, at the gym, or on-the-go! Start Speaking Chinese Today! Rosetta Stone Chinese Edition Levels 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb5500), Your Savings? $435 In Stock: Download fast Start Speaking Arabic Today! Rosetta Stone Arabic Edition Levels 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb5501), Your Savings? $435 In Stock: Download now Start Speaking Japanese Today! Rosetta Stone Japanese Edition Level 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb555i), Your Savings? $435 In Stock: Download fast Start Speaking Russian Today! Rosetta Stone Russian Edition Levels 1,2,3 What you Pay? $65(use discount code FO0Ol9D1550K), Your Savings? $435 In Stock: Download immediately Start Speaking Hebrew Today! Rosetta Stone Hebrew Edition Levels 1,2,3 What you Pay? $65(use discount code FO0Ol9D1550I), Your Savings? $435 In Stock: Download instantly Start Speaking German Today! Rosetta Stone German Edition Levels 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb555u), Your Savings? $435 In Stock: Download today Start Speaking Dutch Today! Rosetta Stone Dutch Edition Levels 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb550e), Your Savings? $435 In Stock: Download quickly Start Speaking Italian Today! Rosetta Stone Italian Edition Levels 1,2,3 What you Pay? $65(use discount code Fs0Ol9Hb555e), Your Savings? $435 In Stock: Download quickly Start Speaking Portuguese Today! Rosetta Stone Portuguese Edit. Levels 1,2,3 What you Pay? $65(use discount code FO0Ol9D1550O), Your Savings? $435 In Stock: Download today Start Speaking Korean Today! Rosetta Stone Korean Edition Levels 1,2,3 What you Pay? $65(use discount code FO0Ol9D15502), Your Savings? $435 In Stock: Download fast See all of our Rosetta Stone products at http://yourfrontrange.com/search.php?q=rosetta All data has been provided with the intent of guaranteeing the customer the best possible experience. Data is current and accurate to the best of yourfrontrange.com knowledge. Product and Manufacturer names and trademarks used for identification purposes only. Thank you for your continued support as a customer. http://yourfrontrange.com/list.php to stop receiving our customer offers. wagoners, when they get their loads into difficulty, is to throw a part off until they lighten it sufficiently, and then go on. I will go this time; but if you get into difficulty again, you must get out yourself." -------------- next part -------------- An HTML attachment was scrubbed... URL: From max at web.servern3.com Tue Sep 28 17:51:43 2010 From: max at web.servern3.com (ArmandoHenrique.com.br) Date: Tue, 28 Sep 2010 14:51:43 -0300 Subject: Armando Henrique - Por que entrei na Politica Message-ID: An HTML attachment was scrubbed... URL: From baranotaa at gmail.com Wed Sep 29 01:15:59 2010 From: baranotaa at gmail.com (Rozier Stanley) Date: Wed, 29 Sep 2010 09:15:59 +0800 Subject: =?GB2312?B?ufq80reiuMTOr7nY09q+2bDsobDX1Nb3tLTQwteoz+7Xyg==?= =?GB2312?B?vfDJ6rGoobG1xM2o1qooMTAuMTUpye7b2iDWoyDpqg==?= Message-ID: ???????????????? ???????10?14???12? ? ??010-59484698 ? ??china_gjfgwpxzx at 163.com ????????? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: ????????????????????????(10.15)?? ? ?.doc Type: application/msword Size: 1004544 bytes Desc: not available URL: From carti.engleza.audio at gmail.com Wed Sep 29 07:31:48 2010 From: carti.engleza.audio at gmail.com (INVATA ENGLEZA USOR SI RAPID) Date: Wed, 29 Sep 2010 09:31:48 +0200 Subject: ACUM INVETI ENGLEZA MULT MAI USOR SI RAPID Message-ID: <201009290759.o8T7xH96011264@mx1.redhat.com> An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Wed Sep 29 01:27:57 2010 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Tue, 28 Sep 2010 22:27:57 -0300 Subject: Mundo Kids, Todos os Mundos em um so lugar Message-ID: <5bf008696231dc557dc49cae0012a08b@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From stye at jcrrll.com Wed Sep 29 14:43:16 2010 From: stye at jcrrll.com (Europe Costantino) Date: Wed, 29 Sep 2010 16:43:16 +0200 Subject: Hat he and the like of him are really the worst friends the truth can poss Message-ID: <4CA34E45.1040907@jcrrll.com> Recite the story of the pilgrim, when young Valiant's heart fell into a burning haste to be a pilgrim too. My brethren, could any lesson be plainer? Read the _Pilgrim's Progress_ with your children. And, after a time, read it again till they call it beautiful, and till you see the same burning haste in their hearts that young Valiant felt in his heart. Circulate the _Pilgrim's Progress_. Make opportunities to give the _Pilgrim's Progress_ to the telegraph boys and errand boys at your door. Never go on a holiday without taking a -------------- next part -------------- A non-text attachment was scrubbed... Name: escutcheon.jpg Type: application/octet-stream Size: 13002 bytes Desc: not available URL: From utrace-devel at redhat.com Wed Sep 29 15:43:22 2010 From: utrace-devel at redhat.com (utrace-devel at redhat.com) Date: Wed, 29 Sep 2010 11:43:22 -0400 Subject: Dear utrace-devel@redhat.com LOVE YOU! Message-ID: <20100929154317.2274.qmail@23-197-134-95.pool.ukrtel.net> Find Your Love Now utrace-devel at redhat.com http://groups.yahoo.com/group/ljhpepcv/message From premiertraining at masteremarketing.com.br Wed Sep 29 18:28:58 2010 From: premiertraining at masteremarketing.com.br (Premier Training) Date: Wed, 29 Sep 2010 14:28:58 -0400 Subject: =?UTF-8?B?UkFEQVIg4oCTIEhBQklMSVRBw4fDg08gUEFSQSBPUEVSQVIgQ09NIElNUE9SVEHDh8OVRVMgRSBFWFBPUlRBw4fDlUVT?= Message-ID: An HTML attachment was scrubbed... URL: From max at web.servern3.com Thu Sep 30 07:51:25 2010 From: max at web.servern3.com (ArmandoHenrique.com.br) Date: Thu, 30 Sep 2010 04:51:25 -0300 Subject: Propostas de trabalho II Message-ID: <6aed39b9515ec0f60fc3fd5c00151d5e@web.servern3.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Sep 30 18:23:20 2010 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 30 Sep 2010 20:23:20 +0200 Subject: gdbstub initial code, v12 Message-ID: <20100930182320.GA17475@redhat.com> Changes: fully implement g/G/p/P. Well, allmost. I didn't expect this is so hairy. And, unfortunately, all this code is x86 specific. I tried to avoid this very much, but failed. Also, it doesn't really support FPU. gdb has its own idea about FPU regs and uses struct i387_fxsave. I failed to understand i387_fxsave_to_cache/i387_cache_to_fxsave, probably I'll simply copy-and-paste this code later. Right now $G doesn't change FPU registers. $P does, but mostly incorrectly. Why gdb doesn't use $p after $P? It always fetches all registers via $G, I don't even know how can I test $p. Perhaps because gdbserver doesn't implement p/P. Btw, I didn't veryfy this, but gdbserver looks obviously wrong wrt 64/32 bit support. "struct reg *reg_defs" is global, it is initalized by ->arch_setup() when we attach the first inferior (or a new one after detach). But every inferior needs its own reg_defs, I think. Otherwize even the simplest x86_fill_gregset/x86_store_gregset can be confused. Next: watchpoints. Oleg. -------------- next part -------------- #include #include #include #include #include #include #include static int o_remote_debug; module_param_named(echo, o_remote_debug, bool, 0); #define BUFFER_SIZE 1152 #define PACKET_SIZE 1152 struct pbuf { char *cur, *pkt; char buf[BUFFER_SIZE]; }; static inline void pb_init(struct pbuf *pb) { pb->cur = pb->buf; pb->pkt = NULL; } enum { U_STOP_IDLE = 0, U_STOP_PENDING, U_STOP_SENT, }; struct ugdb { struct list_head u_processes; struct list_head u_stopped; int u_stop_state; struct mutex u_mutex; spinlock_t u_slock; struct ugdb_thread *u_cur_tinfo, *u_cur_hg, *u_cur_hc; wait_queue_head_t u_wait; int u_err; struct pbuf u_pbuf; char u_cbuf[PACKET_SIZE]; int u_clen; sigset_t u_sig_ign; unsigned int u_no_ack:1, u_allstop:1; }; static inline void ugdb_ck_stopped(struct ugdb *ugdb) { spin_lock(&ugdb->u_slock); WARN_ON(!list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_IDLE); WARN_ON(list_empty(&ugdb->u_stopped) && ugdb->u_stop_state == U_STOP_PENDING); spin_unlock(&ugdb->u_slock); } static struct ugdb *ugdb_create(void) { struct ugdb *ugdb; int err; err = -ENODEV; // XXX: ugly. proc_reg_open() should take care. if (!try_module_get(THIS_MODULE)) goto out; err = -ENOMEM; ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL); if (!ugdb) goto put_module; INIT_LIST_HEAD(&ugdb->u_processes); INIT_LIST_HEAD(&ugdb->u_stopped); mutex_init(&ugdb->u_mutex); spin_lock_init(&ugdb->u_slock); init_waitqueue_head(&ugdb->u_wait); pb_init(&ugdb->u_pbuf); return ugdb; put_module: module_put(THIS_MODULE); out: return ERR_PTR(err); } #define P_DETACHING (1 << 1) #define P_ZOMBIE (1 << 2) struct ugdb_process { int p_pid; int p_state; struct list_head p_threads; struct ugdb *p_ugdb; struct list_head p_processes; }; static inline bool process_alive(struct ugdb_process *process) { return !(process->p_state & P_ZOMBIE); } static inline void mark_process_dead(struct ugdb_process *process) { process->p_state |= P_ZOMBIE; } static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr) { struct ugdb_process *process; process = kzalloc(sizeof(*process), GFP_KERNEL); if (!process) return NULL; process->p_pid = pid_nr; process->p_ugdb = ugdb; INIT_LIST_HEAD(&process->p_threads); list_add_tail(&process->p_processes, &ugdb->u_processes); return process; } #define T_STOP_RUN 0 #define T_STOP_REQ (1 << 0) /* requested by gdb */ #define T_STOP_ALL (1 << 1) /* vCont;c:pX.-1, for report_clone */ #define T_STOP_ACK (1 << 2) /* visible to vStopped */ #define T_STOP_STOPPED (1 << 3) /* reported as stopped to gdb */ /* TASK_TRACED + deactivated ? */ #define T_EV_NONE 0 #define T_EV_EXIT (1 << 24) #define T_EV_SIGN (2 << 24) #define T_EV_TYPE(event) ((0xff << 24) & (event)) #define T_EV_DATA(event) (~(0xff << 24) & (event)) struct ugdb_thread { int t_tid; int t_stop_state; int t_stop_event; bool t_step; // XXX: move me into t_stop_event siginfo_t *t_siginfo; struct ugdb *t_ugdb; struct ugdb_process *t_process; struct list_head t_threads; struct list_head t_stopped; struct pid *t_spid; struct utrace_engine *t_engine; }; static inline bool thread_alive(struct ugdb_thread *thread) { WARN_ON((thread->t_tid != 0) != process_alive(thread->t_process)); return thread->t_tid != 0; } static inline void mark_thread_dead(struct ugdb_thread *thread) { mark_process_dead(thread->t_process); thread->t_tid = 0; } /* * The thread should be alive, and it can't pass ugdb_report_death() * if the caller holds ugdb->u_mutex. However the tracee can be * reaped anyway, pid_task() can return NULL after detach_pid(). */ static inline struct task_struct *thread_to_task(struct ugdb_thread *thread) { BUG_ON(!thread_alive(thread)); return pid_task(thread->t_spid, PIDTYPE_PID); } static struct ugdb_thread *ugdb_create_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (!thread) return NULL; thread->t_tid = pid_vnr(spid); thread->t_spid = get_pid(spid); thread->t_process = process; thread->t_ugdb = process->p_ugdb; INIT_LIST_HEAD(&thread->t_stopped); list_add_tail(&thread->t_threads, &process->p_threads); return thread; } static void ugdb_del_stopped(struct ugdb *ugdb, struct ugdb_thread *thread) { if (!list_empty(&thread->t_stopped)) { WARN_ON(!(thread->t_stop_state & T_STOP_ACK)); spin_lock(&ugdb->u_slock); list_del_init(&thread->t_stopped); if (!(thread->t_stop_state & T_STOP_STOPPED)) { if (ugdb->u_stop_state == U_STOP_PENDING && list_empty(&ugdb->u_stopped)) ugdb->u_stop_state = U_STOP_IDLE; } spin_unlock(&ugdb->u_slock); } thread->t_stop_state = T_STOP_RUN; } static void ugdb_destroy_thread(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; ugdb_ck_stopped(ugdb); ugdb_del_stopped(ugdb, thread); /* NULL if attach fails */ if (thread->t_engine) utrace_engine_put(thread->t_engine); list_del(&thread->t_threads); put_pid(thread->t_spid); kfree(thread); } static int ugdb_set_events(struct ugdb_thread *thread, unsigned long events) { WARN_ON(!thread_alive(thread)); events |= (UTRACE_EVENT(CLONE) | UTRACE_EVENT(DEATH) | UTRACE_EVENT_SIGNAL_ALL); //XXX: I think utrace_get_signal() is buggy !!!!!!!!!!!! events |= UTRACE_EVENT(QUIESCE); return utrace_set_events_pid(thread->t_spid, thread->t_engine, events); } static int ugdb_control(struct ugdb_thread *thread, enum utrace_resume_action action) { // XXX: temporary racy check WARN_ON(!thread_alive(thread) && action != UTRACE_DETACH); return utrace_control_pid(thread->t_spid, thread->t_engine, action); } static const struct utrace_engine_ops ugdb_utrace_ops; static void ugdb_detach_thread(struct ugdb_thread *thread, bool running) { int ret; ret = ugdb_control(thread, UTRACE_DETACH); /* engine->flags == 0, it can't run a callback */ if (!running) return; /* callbacks are no longer possible */ if (!ret) return; if (ret == -EINPROGRESS) { /* * We raced with a callback, it can't be ->report_death(). * However, we can not use utrace_barrier_pid(), it can * hang "forever" until the next utrace_resume() if it * sees ->ops == &utrace_detached_ops set by us, but the * tracee is no longer running. * * But: we have no choice. */ do { ret = utrace_barrier_pid(thread->t_spid, thread->t_engine); } while (ret == -ERESTARTSYS); } else { /* * Nothing can help us to synchronize with ->report_death. * We do not know if it was already called or not, we can't * know if it is running. utrace_barrier_pid() can't help, * it can return zero and then later ->report_death() will * be called. Or it can return -ESRCH just because the task * was alredy released and pid_task() == NULL, but this * doesn't mean ->report_death() can't be called later. * * Fortunately, we know that the tracee is dying or dead, * engine->ops should be changed after ugdb_report_death() * returns UTRACE_DETACH. */ while (thread->t_engine->ops == &ugdb_utrace_ops) { schedule_timeout_uninterruptible(1); } } } /* * returns NULL if raced with exit(), or ERR_PTR(). */ static struct ugdb_thread *ugdb_attach_thread(struct ugdb_process *process, struct pid *spid) { struct ugdb_thread *thread; struct utrace_engine *engine; struct task_struct *task; thread = ugdb_create_thread(process, spid); if (!thread) goto err; engine = utrace_attach_pid(thread->t_spid, UTRACE_ATTACH_CREATE, &ugdb_utrace_ops, thread); if (IS_ERR(engine)) goto free_thread; thread->t_engine = engine; if (ugdb_set_events(thread, 0)) goto detach_thread; return thread; detach_thread: ugdb_detach_thread(thread, false); free_thread: ugdb_destroy_thread(thread); err: rcu_read_lock(); task = pid_task(spid, PIDTYPE_PID); if (task && task->exit_state) task = NULL; rcu_read_unlock(); return task ? ERR_PTR(-ENOMEM) : NULL; } static inline bool is_subthread(struct ugdb_process *process, struct ugdb_thread *thread) { return thread && thread->t_process == process; } static inline void ugdb_reset_tinfo(struct ugdb *ugdb) { ugdb->u_cur_tinfo = NULL; } static void ugdb_destroy_process(struct ugdb_process *process) { struct ugdb *ugdb = process->p_ugdb; struct ugdb_thread *thread; mutex_lock(&ugdb->u_mutex); process->p_state |= P_DETACHING; list_del(&process->p_processes); if (is_subthread(process, ugdb->u_cur_hg)) ugdb->u_cur_hg = NULL; if (is_subthread(process, ugdb->u_cur_hc)) ugdb->u_cur_hc = NULL; /* I hope gdb won't do detach from under qfThreadInfo */ if (ugdb->u_cur_tinfo) { printk(KERN_WARNING "ugdb: detach from under qfThreadInfo\n"); ugdb_reset_tinfo(ugdb); } mutex_unlock(&ugdb->u_mutex); while (!list_empty(&process->p_threads)) { thread = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); ugdb_detach_thread(thread, true); ugdb_destroy_thread(thread); } BUG_ON(!list_empty(&process->p_threads)); kfree(process); } static void ugdb_destroy(struct ugdb *ugdb) { struct ugdb_process *process; while (!list_empty(&ugdb->u_processes)) { process = list_first_entry(&ugdb->u_processes, struct ugdb_process, p_processes); ugdb_destroy_process(process); } BUG_ON(!list_empty(&ugdb->u_processes)); BUG_ON(!list_empty(&ugdb->u_stopped)); module_put(THIS_MODULE); kfree(ugdb); } static struct pid *get_next_pid(struct pid *main, struct pid *curr) { struct task_struct *task; struct sighand_struct *sighand; struct pid *next = NULL; rcu_read_lock(); /* * If task/sighand is NULL we return NULL. This is fine if * the caller is get_first_pid(), we should abort attaching. * * But this can also happen if curr was already attached, * and this is wrong. Fortunately, this is very unlikely * case. The attached sub-thread can't pass ->report_death, * if it was reaped the caller of release_task() must be * ptracer who re-parented this thread. */ task = pid_task(curr, PIDTYPE_PID); if (!task) goto unlock_rcu; // XXX: we need lock_task_sighand() but it is not exported, // so we ran race with de_thread(). sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); for (;;) { task = next_thread(task); // XXX: if main is not leader we can race with exec. if (task_pid(task) == main) break; if (!task->exit_state) { next = get_pid(task_pid(task)); break; } } spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); return next; } static struct pid *get_first_pid(struct pid *main) { struct task_struct *leader; rcu_read_lock(); leader = pid_task(main, PIDTYPE_PID); if (leader && leader->exit_state) leader = NULL; rcu_read_unlock(); /* * The group-leader is alive, try to attach. If it exits * before utrace_set_events(), get_first_pid() will be * called again and it will notice ->exit_state != 0. */ if (leader) return get_pid(main); /* * Try to find the live sub-thread. If the whole group * is dead it returns NULL and the caller aborts. */ return get_next_pid(main, main); } static int ugdb_attach_all_threads(struct ugdb *ugdb, struct ugdb_process *process, struct pid *main_pid) { struct ugdb_thread *thread; struct pid *curr_pid; mutex_lock(&ugdb->u_mutex); for (;;) { curr_pid = get_first_pid(main_pid); if (!curr_pid) goto abort; thread = ugdb_attach_thread(process, curr_pid); put_pid(curr_pid); if (IS_ERR(thread)) goto abort; if (thread) break; } for (;;) { struct pid *next_pid; next_pid = get_next_pid(main_pid, curr_pid); if (!next_pid) break; thread = ugdb_attach_thread(process, next_pid); put_pid(next_pid); if (IS_ERR(thread)) goto abort; if (!thread) continue; curr_pid = next_pid; } mutex_unlock(&ugdb->u_mutex); return 0; abort: mutex_unlock(&ugdb->u_mutex); return -1; } static int ugdb_attach(struct ugdb *ugdb, int pid_nr) { struct pid *main_pid; struct ugdb_process *process; int err; // XXX: check if exists // XXX: check if group leader ? err = -ESRCH; main_pid = find_get_pid(pid_nr); if (!main_pid) goto out; err = -ENOMEM; process = ugdb_create_process(ugdb, pid_nr); if (!process) goto free_pid; err = ugdb_attach_all_threads(ugdb, process, main_pid); if (err) ugdb_destroy_process(process); free_pid: put_pid(main_pid); out: return err; } static struct ugdb_process *ugdb_find_process(struct ugdb *ugdb, int pid) { struct ugdb_process *process; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (process->p_pid == pid) return process; } return NULL; } static struct ugdb_thread *ugdb_find_thread(struct ugdb *ugdb, int pid, int tid) { struct ugdb_process *process; struct ugdb_thread *thread; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (!tid || thread->t_tid == tid) return thread; } if (pid) break; } return NULL; } static int ugdb_detach(struct ugdb *ugdb, int pid) { struct ugdb_process *process = ugdb_find_process(ugdb, pid); if (!process) return -1; ugdb_destroy_process(process); return 0; } #define CUR_TINFO_END ((struct ugdb_thread *)1) static struct ugdb_thread *ugdb_advance_tinfo(struct ugdb *ugdb) { struct ugdb_thread *cur, *nxt; struct ugdb_process *process; cur = ugdb->u_cur_tinfo; if (cur == CUR_TINFO_END) { ugdb->u_cur_tinfo = NULL; return NULL; } if (!cur) { list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { cur = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } if (!cur) return NULL; } process = cur->t_process; if (list_is_last(&cur->t_threads, &process->p_threads)) { nxt = CUR_TINFO_END; list_for_each_entry_continue(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (!list_empty(&process->p_threads)) { nxt = list_first_entry(&process->p_threads, struct ugdb_thread, t_threads); break; } } } else { nxt = list_first_entry(&cur->t_threads, struct ugdb_thread, t_threads); } ugdb->u_cur_tinfo = nxt; return cur; } // ----------------------------------------------------------------------------- static bool ugdb_add_stopped(struct ugdb_thread *thread, int stop_event) { struct ugdb *ugdb = thread->t_ugdb; bool ret = false; ugdb_ck_stopped(ugdb); spin_lock(&ugdb->u_slock); if (stop_event == T_EV_NONE) { if (WARN_ON(thread->t_stop_state & T_STOP_ACK)) goto unlock; if (WARN_ON(!list_empty(&thread->t_stopped))) goto unlock; /* raced with ugdb_cont_thread() */ if (!(thread->t_stop_state & T_STOP_REQ)) goto unlock; } if (thread->t_stop_state & T_STOP_ACK) { if (thread->t_stop_state & T_STOP_STOPPED) /* * Alas, we can't report this event. We already * reported T00 and there is no way to inform gdb * the state of tracee was changed. */ goto unlock; } else { WARN_ON(thread->t_stop_state & T_STOP_STOPPED); thread->t_stop_state |= T_STOP_ACK; list_add_tail(&thread->t_stopped, &ugdb->u_stopped); if (ugdb->u_stop_state == U_STOP_IDLE) { ugdb->u_stop_state = U_STOP_PENDING; wake_up_all(&ugdb->u_wait); } } thread->t_stop_event = stop_event; ret = true; unlock: spin_unlock(&ugdb->u_slock); return ret; } static void ugdb_process_exit(struct ugdb_thread *thread) { struct ugdb *ugdb = thread->t_ugdb; int status; BUG_ON(!thread_alive(thread)); ugdb_del_stopped(ugdb, thread); mark_thread_dead(thread); // XXX: OOPS, we can't read ->signal->group_exit_code !!! status = current->exit_code; if (ugdb_add_stopped(thread, T_EV_EXIT | status)) return; WARN_ON(1); } static int ugdb_stop_thread(struct ugdb_thread *thread, bool all) { struct ugdb *ugdb = thread->t_ugdb; int err; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); if (thread->t_stop_state != T_STOP_RUN) { if (!all || (thread->t_stop_state & T_STOP_ALL)) return 0; /* * Otherwise we should set T_STOP_ALL anyway, * * (gdb) interrupt & * (gbd) interrupt -a & * * to ensure -a actually works if it races with clone. */ } err = -EALREADY; spin_lock(&ugdb->u_slock); if (thread->t_stop_state == T_STOP_RUN) { thread->t_stop_state = T_STOP_REQ; err = 0; } /* * We hold ugdb->u_mutex, we can't race with ugdb_report_clone(). * ugdb->u_slock protects us against ugdb_add_stopped(). We can * change ->t_stop_state even if we did not initiate this stop. */ if (all) thread->t_stop_state |= T_STOP_ALL; spin_unlock(&ugdb->u_slock); if (err) return 0; // XXX: we don't do UTRACE_STOP! this means we can't // stop TASK_STOPEED task. Need to discuss jctl issues. // if we do UTRACE_STOP we should call ugdb_add_stopped(). ugdb_set_events(thread, UTRACE_EVENT(QUIESCE)); err = ugdb_control(thread, UTRACE_INTERRUPT); if (err && err != -EINPROGRESS) return err; return 1; } static int ugdb_cont_thread(struct ugdb_thread *thread, bool all, bool step) { struct ugdb *ugdb = thread->t_ugdb; int ret; WARN_ON(!thread_alive(thread)); ugdb_ck_stopped(ugdb); // XXX: gdb shouldn't explicitly cont an unreported thread WARN_ON(!all && !(thread->t_stop_state & T_STOP_STOPPED)); if (thread->t_stop_state == T_STOP_RUN) return 0; spin_lock(&ugdb->u_slock); /* * Nothing to do except clear the pending T_STOP_REQ. */ ret = 0; if (!(thread->t_stop_state & T_STOP_ACK)) goto set_run; /* * Alas. Thanks to remote protocol, we can't cont this * thread. We probably already sent the notification, we * can do nothing except ack that %Stop later in response * to vStopped. * * OTOH, gdb shouldn't send 'c' if this thread was not * reported as stopped. However, this means that gdb can * see the new %Stop:T00 notification after vCont;c:pX.-1, * it should handle this case correctly anyway. I hope. * * If this stop was not initiated by gdb we should not * cancel it too, this event should be reported first. */ ret = -1; if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; ret = 1; list_del_init(&thread->t_stopped); set_run: thread->t_stop_state = T_STOP_RUN; unlock: spin_unlock(&ugdb->u_slock); if (ret >= 0) { unsigned long events = 0; enum utrace_resume_action action = UTRACE_RESUME; thread->t_step = step; if (step) { /* to correctly step over syscall insn */ events |= UTRACE_EVENT(SYSCALL_EXIT); action = UTRACE_SINGLESTEP; } // XXX: OK, this all is racy, and I do not see any // solution except: implement UTRACE_STOP_STICKY and // move this code up under the lock, or add // utrace_engine_ops->notify_stopped(). // 1. UTRACE_RESUME is racy, this is fixeable. // 2. we need utrace_barrier() to close the race // with the callback which is going to return // UTRACE_STOP, but: // a) we can deadlock (solveable) // b) in this case UTRACE_RESUME can race with // another stop initiated by tracee itself. ugdb_set_events(thread, events); ugdb_control(thread, action); } return ret; } static struct ugdb_thread *ugdb_next_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread = NULL; // XXX: temporary racy check WARN_ON(ugdb->u_stop_state == U_STOP_IDLE); spin_lock(&ugdb->u_slock); if (list_empty(&ugdb->u_stopped)) { ugdb->u_stop_state = U_STOP_IDLE; } else { ugdb->u_stop_state = U_STOP_SENT; thread = list_first_entry(&ugdb->u_stopped, struct ugdb_thread, t_stopped); thread->t_stop_state |= T_STOP_STOPPED; list_del_init(&thread->t_stopped); } spin_unlock(&ugdb->u_slock); return thread; } // ----------------------------------------------------------------------------- static bool ugdb_stop_pending(struct ugdb_thread *thread) { if (!(thread->t_stop_state & T_STOP_REQ)) return false; if (!(thread->t_stop_state & T_STOP_ACK)) return ugdb_add_stopped(thread, T_EV_NONE); return true; } static u32 ugdb_report_quiesce(u32 action, struct utrace_engine *engine, unsigned long event) { struct ugdb_thread *thread = engine->data; WARN_ON(!thread_alive(thread)); /* ensure SIGKILL can't race with stop/cont in progress */ if (event != UTRACE_EVENT(DEATH)) { if (ugdb_stop_pending(thread)) return UTRACE_STOP; } return utrace_resume_action(action); } static int cont_signal(struct ugdb_thread *thread, struct k_sigaction *return_ka) { int signr = T_EV_DATA(thread->t_stop_event); siginfo_t *info = thread->t_siginfo; thread->t_siginfo = NULL; if (WARN_ON(!valid_signal(signr))) return 0; if (!signr) return signr; /* * Update the siginfo structure if the signal has changed. */ if (info->si_signo != signr) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = 0; info->si_uid = 0; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, info, current); signr = 0; } else { spin_lock_irq(¤t->sighand->siglock); *return_ka = current->sighand->action[signr - 1]; spin_unlock_irq(¤t->sighand->siglock); } return signr; } static u32 ugdb_report_signal(u32 action, struct utrace_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { struct ugdb_thread *thread = engine->data; struct ugdb *ugdb = thread->t_ugdb; int signr; WARN_ON(!thread_alive(thread)); switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: if (WARN_ON(thread->t_siginfo)) thread->t_siginfo = NULL; if (thread->t_step) { WARN_ON(orig_ka); // user_single_step_siginfo(current, regs, info); memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; break; } /* Fall through */ default: if (orig_ka) break; /* * It was UTRACE_SIGNAL_REPORT, but another tracer has * changed utrace_report->result to deliver or stop. * Fall through. */ case UTRACE_SIGNAL_REPORT: if (!thread->t_siginfo) { /* UTRACE_INTERRUPT from ugdb_report_syscall_exit() */ if (thread->t_step) { WARN_ON(orig_ka); // user_single_step_siginfo(current, regs, info); memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; break; } } else { if (WARN_ON(thread->t_siginfo != info)) return action; WARN_ON(T_EV_TYPE(thread->t_stop_event) != T_EV_SIGN); signr = cont_signal(thread, return_ka); if (signr) { /* * Consider: * * (gdb) signal SIG & * (gdb) interrupt * * We shouldn't miss the new stop request, so * we do not return from here. */ action = UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; } } if (ugdb_stop_pending(thread)) return UTRACE_STOP | utrace_signal_action(action); if (thread->t_step) return UTRACE_SINGLESTEP | utrace_signal_action(action); return action; } WARN_ON(thread->t_siginfo); signr = info->si_signo; if (WARN_ON(!signr || !valid_signal(signr))) return action; if (sigismember(&ugdb->u_sig_ign, signr)) return action; if (ugdb_add_stopped(thread, T_EV_SIGN | signr)) { thread->t_siginfo = info; /* * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->t_siginfo before return from get_signal_to_deliver(). */ if (utrace_control(current, engine, UTRACE_INTERRUPT)) WARN_ON(1); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } /* * We already reported T00 to gdb. We can't change our state, * we are already stopped from gdb pov. Push back this signal * to report it later, after "continue". * * Not multitrace-friendly. */ return UTRACE_STOP | UTRACE_SIGNAL_REPORT | UTRACE_SIGNAL_HOLD; } static u32 ugdb_report_syscall_exit(u32 action, struct utrace_engine *engine, struct pt_regs *regs) { struct ugdb_thread *thread = engine->data; if (thread->t_step) return UTRACE_INTERRUPT; printk(KERN_INFO "ugdb: unexpected SYSCALL_EXIT\n"); return action; } static bool is_already_attached(struct ugdb_process *process, struct task_struct *task) { struct ugdb_thread *thread; if (likely(!task_utrace_flags(task))) return false; /* * Currently there is no way to know if it was attached by us. * We can't trust utrace_attach_task(UTRACE_ATTACH_MATCH_OPS), * ugdb attaches without UTRACE_ATTACH_EXCLUSIVE. We have to * check every attached thread. * * This is really bad, but without multitracing this can only * happen in unlikely case right after ugdb_attach_all_threads(). */ list_for_each_entry(thread, &process->p_threads, t_threads) { if (thread->t_spid == task_pid(task)) return true; } return false; } static u32 ugdb_report_clone(u32 action, struct utrace_engine *engine, unsigned long clone_flags, struct task_struct *task) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; struct ugdb_thread *new_thread; WARN_ON(!thread_alive(thread)); if (!(clone_flags & CLONE_THREAD)) goto out; mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; /* * This can only happen if we raced with ugdb_attach() which * could attach both current and the new PF_STARTING child. */ if (unlikely(is_already_attached(process, task))) goto unlock; new_thread = ugdb_attach_thread(process, task_pid(task)); BUG_ON(!new_thread); if (WARN_ON(IS_ERR(new_thread))) goto unlock; if (thread->t_stop_state & T_STOP_ALL) ugdb_stop_thread(new_thread, false); unlock: mutex_unlock(&ugdb->u_mutex); out: return utrace_resume_action(action); } static u32 ugdb_report_death(struct utrace_engine *engine, bool group_dead, int signal) { struct ugdb_thread *thread = engine->data; struct ugdb_process *process = thread->t_process; struct ugdb *ugdb = thread->t_ugdb; WARN_ON(!thread_alive(thread)); mutex_lock(&ugdb->u_mutex); if (process->p_state & P_DETACHING) goto unlock; if (ugdb->u_cur_hg == thread) ugdb->u_cur_hg = NULL; if (ugdb->u_cur_hc == thread) ugdb->u_cur_hc = NULL; if (ugdb->u_cur_tinfo == thread) ugdb_advance_tinfo(ugdb); if (list_is_singular(&process->p_threads)) ugdb_process_exit(thread); else ugdb_destroy_thread(thread); unlock: mutex_unlock(&ugdb->u_mutex); return UTRACE_DETACH; } static const struct utrace_engine_ops ugdb_utrace_ops = { .report_quiesce = ugdb_report_quiesce, .report_signal = ugdb_report_signal, .report_syscall_exit = ugdb_report_syscall_exit, .report_clone = ugdb_report_clone, .report_death = ugdb_report_death, }; // ----------------------------------------------------------------------------- static inline int pb_size(struct pbuf *pb) { return pb->cur - pb->buf; } static inline int pb_room(struct pbuf *pb) { return pb->buf + BUFFER_SIZE - pb->cur; } static inline void pb_putc(struct pbuf *pb, char c) { if (WARN_ON(pb->cur >= pb->buf + BUFFER_SIZE-1)) return; *pb->cur++ = c; } static void pb_memcpy(struct pbuf *pb, const void *data, int size) { if (WARN_ON(size > pb_room(pb))) return; memcpy(pb->cur, data, size); pb->cur += size; } static inline void pb_puts(struct pbuf *pb, const char *s) { pb_memcpy(pb, s, strlen(s)); } static inline void pb_putb(struct pbuf *pb, unsigned char val) { static char hex[] = "0123456789abcdef"; pb_putc(pb, hex[(val & 0xf0) >> 4]); pb_putc(pb, hex[(val & 0x0f) >> 0]); } static void pb_putbs(struct pbuf *pb, const char *data, int size) { while (size--) pb_putb(pb, *data++); } static inline void __pb_start(struct pbuf *pb, char pref) { WARN_ON(pb->pkt); pb_putc(pb, pref); pb->pkt = pb->cur; } static inline void pb_start(struct pbuf *pb) { return __pb_start(pb, '$'); } static inline void pb_cancel(struct pbuf *pb) { if (WARN_ON(!pb->pkt)) return; pb->cur = pb->pkt - 1; pb->pkt = NULL; } static void pb_end(struct pbuf *pb) { unsigned char csm = 0; char *pkt = pb->pkt; pb->pkt = NULL; if (WARN_ON(!pkt)) return; while (pkt < pb->cur) { /* pb_qfer() can write '%' */ WARN_ON(*pkt == '$' || *pkt == '#'); csm += (unsigned char)*pkt++; } pb_putc(pb, '#'); pb_putb(pb, csm); } static inline void pb_packs(struct pbuf *pb, const char *s) { pb_start(pb); pb_puts(pb, s); pb_end(pb); } static void __attribute__ ((format(printf, 3, 4))) __pb_format(struct pbuf *pb, bool whole_pkt, const char *fmt, ...) { int room = pb_room(pb), size; va_list args; if (whole_pkt) pb_start(pb); va_start(args, fmt); size = vsnprintf(pb->cur, room, fmt, args); va_end(args); if (WARN_ON(size > room)) return; pb->cur += size; if (whole_pkt) pb_end(pb); } #define pb_printf(pb, args...) __pb_format((pb), false, args) #define pb_packf(pb, args...) __pb_format((pb), true, args) static int pb_qfer(struct pbuf *pb, const void *_data, int len, bool more) { const unsigned char *data = _data; int i; if (pb_room(pb) < 3 + len * 2) { WARN_ON(1); return -EOVERFLOW; } pb_start(pb); pb_putc(pb, more ? 'm' : 'l'); for (i = 0; i < len; ++i) { unsigned char c = data[i]; if (c == '$' || c == '#' || c == '}' || c == '*') { pb_putc(pb, '}'); c ^= 0x20; } pb_putc(pb, c); } pb_end(pb); return 0; } static inline void *pb_alloc_bs(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < 2 * size + 4)) return NULL; return pb->cur + size + 1; } static inline void *pb_alloc_tmp(struct pbuf *pb, int size) { if (unlikely(pb_room(pb) < size)) return NULL; return pb->cur + BUFFER_SIZE - size; } static inline void pb_flush(struct pbuf *pb, int size) { int keep = pb_size(pb) - size; if (keep) memmove(pb->buf, pb->buf + size, keep); pb->cur -= size; } static int pb_copy_to_user(struct pbuf *pb, char __user *ubuf, int size) { int copy = min(size, pb_size(pb)); if (!copy) return -EAGAIN; if (o_remote_debug) printk(KERN_INFO "<= %.*s\n", min(copy, 64), pb->buf); if (copy_to_user(ubuf, pb->buf, copy)) return -EFAULT; pb_flush(pb, copy); return copy; } // ----------------------------------------------------------------------------- // XXX: include/gdb/signals.h:target_signal // incomplete: 7, 29, rt? static int to_gdb_sigmap[] = { [SIGHUP] = 1, [SIGINT] = 2, [SIGQUIT] = 3, [SIGILL] = 4, [SIGTRAP] = 5, [SIGABRT] = 6, [SIGIOT] = 0, /* ??? */ [SIGBUS] = 10, [SIGFPE] = 8, [SIGKILL] = 9, [SIGUSR1] = 30, [SIGSEGV] = 11, [SIGUSR2] = 31, [SIGPIPE] = 13, [SIGALRM] = 14, [SIGTERM] = 15, [SIGSTKFLT] = 0, /* ??? */ [SIGCHLD] = 20, [SIGCONT] = 19, [SIGSTOP] = 17, [SIGTSTP] = 18, [SIGTTIN] = 21, [SIGTTOU] = 22, [SIGURG] = 16, [SIGXCPU] = 24, [SIGXFSZ] = 25, [SIGVTALRM] = 26, [SIGPROF] = 27, [SIGWINCH] = 28, [SIGIO] = 23, [SIGPWR] = 32, [SIGSYS] = 12, }; static int sig_to_gdb(unsigned sig) { if (sig < ARRAY_SIZE(to_gdb_sigmap) && to_gdb_sigmap[sig]) return to_gdb_sigmap[sig]; return sig; } static int sig_from_gdb(unsigned sig) { int i; // XXX: valid_signal() is wrong, gdb has its own idea // about signals. fix to_gdb_sigmap[]. if (!sig || !valid_signal(sig)) return 0; for (i = 0; i < ARRAY_SIZE(to_gdb_sigmap); i++) { if (to_gdb_sigmap[i] == sig) return i; } return sig; } static int ugdb_report_stopped(struct ugdb *ugdb, bool async) { struct ugdb_thread *thread; int pid, tid, event, data; struct pbuf *pb; char ex_r; mutex_lock(&ugdb->u_mutex); thread = ugdb_next_stopped(ugdb); if (!thread) goto unlock; event = thread->t_stop_event; WARN_ON(thread_alive(thread) != (T_EV_TYPE(event) != T_EV_EXIT)); pid = thread->t_process->p_pid; tid = thread->t_tid; unlock: mutex_unlock(&ugdb->u_mutex); if (!thread) return false; pb = &ugdb->u_pbuf; // XXX: damn, cleanup me... if (async) { __pb_start(pb, '%'); pb_puts(pb, "Stop:"); } else { pb_start(pb); } data = T_EV_DATA(event); switch (T_EV_TYPE(event)) { case T_EV_EXIT: if (data & 0xff) { data = sig_to_gdb(data & 0xff); ex_r = 'X'; } else { data >>= 8; ex_r = 'W'; } pb_printf(pb, "%c%x;process:%x", ex_r, data, pid); ugdb_destroy_process(thread->t_process); break; case T_EV_SIGN: case T_EV_NONE: pb_printf(pb, "T%02xthread:p%x.%x;", sig_to_gdb(data), pid, tid); break; default: printk(KERN_INFO "ugdb: bad stop event %x\n", event); } pb_end(pb); return true; } const char *handle_vstopped(struct ugdb *ugdb) { if (ugdb->u_stop_state != U_STOP_SENT) return "E01"; if (ugdb_report_stopped(ugdb, false)) return NULL; return "OK"; } static const char *handle_thread_info(struct ugdb *ugdb, bool start) { struct ugdb_thread *thread; int pid = 0, tid; mutex_lock(&ugdb->u_mutex); if (start) ugdb_reset_tinfo(ugdb); else if (!ugdb->u_cur_tinfo) printk(KERN_INFO "ugdb: unexpected qsThreadInfo\n"); thread = ugdb_advance_tinfo(ugdb); if (thread) { pid = thread->t_process->p_pid; tid = thread->t_tid; } mutex_unlock(&ugdb->u_mutex); if (!pid) return start ? "E01" : "l"; pb_packf(&ugdb->u_pbuf, "mp%x.%x", pid, tid); return NULL; } static char *parse_xid(char *str, int *ppid, bool multi) { if (*str == '-') { str++; if (multi && *str++ == '1') *ppid = -1; else str = NULL; } else { char *cur = str; *ppid = simple_strtoul(cur, &str, 16); if (str == cur) str = NULL; } return str; } static char *parse_pid_tid(char *str, int *ppid, int *ptid, bool multi) { if (*str++ != 'p') return NULL; str = parse_xid(str, ppid, multi); if (!str) return NULL; if (*str++ != '.') return NULL; str = parse_xid(str, ptid, multi); if (!str) return NULL; return str; } static const char *handle_set_cur(struct ugdb *ugdb, char *cmd) { struct ugdb_thread **pthread; int pid, tid; switch (*cmd++) { case 'g': pthread = &ugdb->u_cur_hg; break; case 'c': pthread = &ugdb->u_cur_hc; break; default: goto err; } if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); *pthread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (*pthread) return "OK"; err: return "E01"; } static const char *handle_ck_alive(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; int pid = 0, tid; if (!parse_pid_tid(cmd, &pid, &tid, false)) goto err; mutex_lock(&ugdb->u_mutex); thread = ugdb_find_thread(ugdb, pid, tid); mutex_unlock(&ugdb->u_mutex); if (thread) return "OK"; err: return "E01"; } static int parse_pid(char *str) { int pid; if (!parse_xid(str, &pid, false)) return 0; return pid; } static const char *handle_vattach(struct ugdb *ugdb, char *cmd) { int pid = parse_pid(cmd); if (pid && !ugdb_attach(ugdb, pid)) return "OK"; return "E01"; } static const char *handle_detach(struct ugdb *ugdb, char *cmd) { int pid; if (*cmd++ != ';') goto err; pid = parse_pid(cmd); if (pid && !ugdb_detach(ugdb, pid)) return "OK"; err: return "E01"; } typedef int (*each_func_t)(struct ugdb_thread *, void *); static int ugdb_do_each_thread(struct ugdb *ugdb, int pid, int tid, each_func_t func, void *arg) { struct ugdb_process *process; struct ugdb_thread *thread; int ret = -ESRCH; list_for_each_entry(process, &ugdb->u_processes, p_processes) { if (unlikely(!process_alive(process))) continue; if (pid > 0 && process->p_pid != pid) continue; list_for_each_entry(thread, &process->p_threads, t_threads) { if (WARN_ON(!thread_alive(thread))) continue; if (tid > 0 && thread->t_tid != tid) continue; ret = func(thread, arg); if (ret) goto out; if (tid >= 0) break; } if (pid >= 0) break; } out: return ret; } static int do_stop_thread(struct ugdb_thread *thread, void *arg) { ugdb_stop_thread(thread, arg != NULL); return 0; } static int do_cont_thread(struct ugdb_thread *thread, void *arg) { ugdb_cont_thread(thread, arg != NULL, false); return 0; } static const char *handle_vcont(struct ugdb *ugdb, char *cmd) { int pid, tid; void *arg; int ret; switch (*cmd ++) { default: return "E01"; case '?': return "vCont;t"; case ';': break; } // XXX: Discuss the generic case! currently trivial. if (*cmd++ != 't') return "E01"; pid = tid = -1; if (*cmd++ == ':') { if (!parse_pid_tid(cmd, &pid, &tid, true)) return "E01"; } arg = (tid >= 0) ? NULL : (void*)1; mutex_lock(&ugdb->u_mutex); // XXX: currently we only report -ESRCH ret = ugdb_do_each_thread(ugdb, pid, tid, do_stop_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret < 0 ? "E01" : "OK"; } static int thread_cont_signal(struct ugdb_thread *thread, int signr) { /* * T_STOP_STOPPED was set under ->u_slock so we can't race * with ugdb_add_stopped() and get the wrong t_stop_event. * And, the tracee never changes it after T_STOP_STOPPED. */ switch (T_EV_TYPE(thread->t_stop_event)) { case T_EV_SIGN: WARN_ON(!T_EV_DATA(thread->t_stop_event)); thread->t_stop_event = T_EV_SIGN | signr; break; default: if (!signr) break; // XXX: temporary hack, will be reported. // but perhaps this is what we want ??? kill_pid(thread->t_spid, signr, 0); break; } return 0; } static const char *handle_c(struct ugdb *ugdb, char *cmd) { struct ugdb_thread *thread; const char *rc = "E01"; int gdbsig, signr = 0; bool step; step = (*cmd == 'S' || *cmd == 's'); switch (*cmd++) { case 'C': case 'S': gdbsig = simple_strtoul(cmd, &cmd, 16); if (!gdbsig) return rc; signr = sig_from_gdb(gdbsig); if (!signr) printk(KERN_INFO "ugdb: sorry, can't map signal %d\n", gdbsig); if (*cmd == ';') ++cmd; /* fall */ case 'c': case 's': if (!*cmd) break; printk(KERN_INFO "ugdb: $c ADDR not implemented\n"); return rc; break; } mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hc; if (!thread) goto unlock; /* * Otherwise I do not know what to do if sig/step, and anyway * I don't think gdb can try to cont a thread which was not * reported as stopped. */ if (!(thread->t_stop_state & T_STOP_STOPPED)) goto unlock; if (thread_cont_signal(thread, signr)) goto unlock; if (ugdb_cont_thread(thread, false, step) <= 0) goto unlock; rc = "OK"; unlock: mutex_unlock(&ugdb->u_mutex); return rc; } static const char *handle_qpass_signals(struct ugdb *ugdb, char *cmd) { sigset_t *set = &ugdb->u_sig_ign; sigemptyset(set); while (*cmd) { char *end; int sig = simple_strtoul(cmd, &end, 16); if (cmd == end || *end != ';') return "E01"; cmd = end + 1; sig = sig_from_gdb(sig); if (!sig) // XXX: to_gdb_sigmap[] incomplete... // return "E01"; continue; sigaddset(set, sig); } return "OK"; } // ----------------------------------------------------------------------------- static struct task_struct * ugdb_prepare_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { struct ugdb_thread *thread; struct task_struct *task; int err; mutex_lock(&ugdb->u_mutex); thread = ugdb->u_cur_hg; if (!thread || !(thread->t_stop_state & T_STOP_STOPPED)) goto err; // XXX: u_cur_hg can't exit, we hold the mutex task = thread_to_task(thread); if (!task) goto err; for (;;) { if (fatal_signal_pending(current)) goto err; err = utrace_prepare_examine(task, thread->t_engine, exam); if (!err) break; if (err == -ESRCH) goto err; schedule_timeout_interruptible(1); } return task; err: mutex_unlock(&ugdb->u_mutex); return NULL; } // XXX: we hold the mutex in between, but only because we can't // use get_task_struct/put_task_struct. static int ugdb_finish_examine(struct ugdb *ugdb, struct utrace_examiner *exam) { // XXX: u_cur_hg can't exit, we hold the mutex struct ugdb_thread *thread = ugdb->u_cur_hg; struct task_struct *task = thread_to_task(thread); int ret = -ESRCH; if (task) ret = utrace_finish_examine(task, thread->t_engine, exam); mutex_unlock(&ugdb->u_mutex); return ret; } #define REGSET_GENERAL 0 #define REGSET_FP 1 // stolen from gdb-7.1/gdb/gdbserver/linux-x86-low.c static int x86_64_regmap[] = { 80, 40, 88, 96, 104, 112, 32, 152, 72, 64, 56, 48, 24, 16, 8, 0, 128, 144, 136, 160, 184, 192, 200, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, }; static char *handle_getregs(struct ugdb *ugdb) { struct utrace_examiner exam; struct task_struct *task; const struct user_regset_view *view; const struct user_regset *rset; struct user_regs_struct *pregs; int rn; static int pkt_size; if (!pkt_size) { int sz = 0; for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs < 0) continue; if (offs > (sizeof(*pregs) - sizeof(long))) { printk(KERN_INFO "XXX: x86_64_regmap is wrong!\n"); ugdb->u_err = -EINVAL; goto err; } sz += sizeof(long) * 2; } pkt_size = sz; } if (pb_room(&ugdb->u_pbuf) < 4 + pkt_size + sizeof(*pregs)) { printk(KERN_INFO "XXX: getregs ENOMEM %d %ld\n", pkt_size, sizeof(*pregs)); goto err; } pregs = pb_alloc_tmp(&ugdb->u_pbuf, sizeof(*pregs)); BUG_ON(pregs + 1 != (void*)ugdb->u_pbuf.cur + BUFFER_SIZE); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; view = task_user_regset_view(task); rset = view->regsets + REGSET_GENERAL; rset->get(task, rset, 0, sizeof(*pregs), pregs, NULL); if (ugdb_finish_examine(ugdb, &exam)) goto err; pb_start(&ugdb->u_pbuf); for (rn = 0; rn < ARRAY_SIZE(x86_64_regmap); ++rn) { int offs = x86_64_regmap[rn]; if (offs >= 0) pb_putbs(&ugdb->u_pbuf, (void*)pregs + offs, sizeof(long)); } WARN_ON(pb_room(&ugdb->u_pbuf) < sizeof(*pregs)); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } #define MAX_REG_SIZE 16 struct gdbreg { unsigned short gdb_size, gdb_offs, rs_setno, usr_offs; }; // gdb/gdbserver/i387-fp.c:i387_fxsave struct gdb_i387_fxsave { unsigned short fctrl; unsigned short fstat; unsigned short ftag; unsigned short fop; unsigned int fioff; unsigned short fiseg; unsigned short pad1; unsigned int fooff; unsigned short foseg; unsigned short pad12; unsigned int mxcsr; unsigned int pad3; unsigned char st_space[128]; unsigned char xmm_space[256]; }; #define FPU__(mem) \ .rs_setno = REGSET_FP, \ .usr_offs = offsetof(struct gdb_i387_fxsave, mem) #define GEN__(mem) \ .rs_setno = REGSET_GENERAL, \ .usr_offs = offsetof(struct user_regs_struct, mem) /* generated from gdb/regformats/reg-x86-64-linux.dat */ struct gdbreg gdb_regmap_64[] = { [ 0] = { .gdb_size = 8, .gdb_offs = 0, GEN__(ax) }, [ 1] = { .gdb_size = 8, .gdb_offs = 8, GEN__(bx) }, [ 2] = { .gdb_size = 8, .gdb_offs = 16, GEN__(cx) }, [ 3] = { .gdb_size = 8, .gdb_offs = 24, GEN__(dx) }, [ 4] = { .gdb_size = 8, .gdb_offs = 32, GEN__(si) }, [ 5] = { .gdb_size = 8, .gdb_offs = 40, GEN__(di) }, [ 6] = { .gdb_size = 8, .gdb_offs = 48, GEN__(bp) }, [ 7] = { .gdb_size = 8, .gdb_offs = 56, GEN__(sp) }, [ 8] = { .gdb_size = 8, .gdb_offs = 64, GEN__(r8) }, [ 9] = { .gdb_size = 8, .gdb_offs = 72, GEN__(r9) }, [10] = { .gdb_size = 8, .gdb_offs = 80, GEN__(r10) }, [11] = { .gdb_size = 8, .gdb_offs = 88, GEN__(r11) }, [12] = { .gdb_size = 8, .gdb_offs = 96, GEN__(r12) }, [13] = { .gdb_size = 8, .gdb_offs = 104, GEN__(r13) }, [14] = { .gdb_size = 8, .gdb_offs = 112, GEN__(r14) }, [15] = { .gdb_size = 8, .gdb_offs = 120, GEN__(r15) }, [16] = { .gdb_size = 8, .gdb_offs = 128, GEN__(ip) }, [17] = { .gdb_size = 4, .gdb_offs = 136, GEN__(flags) }, [18] = { .gdb_size = 4, .gdb_offs = 140, GEN__(cs) }, [19] = { .gdb_size = 4, .gdb_offs = 144, GEN__(ss) }, [20] = { .gdb_size = 4, .gdb_offs = 148, GEN__(ds) }, [21] = { .gdb_size = 4, .gdb_offs = 152, GEN__(es) }, [22] = { .gdb_size = 4, .gdb_offs = 156, GEN__(fs) }, [23] = { .gdb_size = 4, .gdb_offs = 160, GEN__(gs) }, [24] = { .gdb_size = 10, .gdb_offs = 164, FPU__(st_space[0]) }, [25] = { .gdb_size = 10, .gdb_offs = 174, FPU__(st_space[16]) }, [26] = { .gdb_size = 10, .gdb_offs = 184, FPU__(st_space[32]) }, [27] = { .gdb_size = 10, .gdb_offs = 194, FPU__(st_space[48]) }, [28] = { .gdb_size = 10, .gdb_offs = 204, FPU__(st_space[64]) }, [29] = { .gdb_size = 10, .gdb_offs = 214, FPU__(st_space[80]) }, [30] = { .gdb_size = 10, .gdb_offs = 224, FPU__(st_space[96]) }, [31] = { .gdb_size = 10, .gdb_offs = 234, FPU__(st_space[112]) }, [32] = { .gdb_size = 4, .gdb_offs = 244, FPU__(fctrl) }, [33] = { .gdb_size = 4, .gdb_offs = 248, FPU__(fstat) }, [34] = { .gdb_size = 4, .gdb_offs = 252, FPU__(ftag) }, [35] = { .gdb_size = 4, .gdb_offs = 256, FPU__(fiseg) }, [36] = { .gdb_size = 4, .gdb_offs = 260, FPU__(fioff) }, [37] = { .gdb_size = 4, .gdb_offs = 264, FPU__(foseg) }, [38] = { .gdb_size = 4, .gdb_offs = 268, FPU__(fooff) }, [39] = { .gdb_size = 4, .gdb_offs = 272, FPU__(fop) }, [40] = { .gdb_size = 16, .gdb_offs = 276, FPU__(xmm_space[0]) }, [41] = { .gdb_size = 16, .gdb_offs = 292, FPU__(xmm_space[16]) }, [42] = { .gdb_size = 16, .gdb_offs = 308, FPU__(xmm_space[32]) }, [43] = { .gdb_size = 16, .gdb_offs = 324, FPU__(xmm_space[48]) }, [44] = { .gdb_size = 16, .gdb_offs = 340, FPU__(xmm_space[64]) }, [45] = { .gdb_size = 16, .gdb_offs = 356, FPU__(xmm_space[80]) }, [46] = { .gdb_size = 16, .gdb_offs = 372, FPU__(xmm_space[96]) }, [47] = { .gdb_size = 16, .gdb_offs = 388, FPU__(xmm_space[112]) }, [48] = { .gdb_size = 16, .gdb_offs = 404, FPU__(xmm_space[128]) }, [49] = { .gdb_size = 16, .gdb_offs = 420, FPU__(xmm_space[144]) }, [50] = { .gdb_size = 16, .gdb_offs = 436, FPU__(xmm_space[160]) }, [51] = { .gdb_size = 16, .gdb_offs = 452, FPU__(xmm_space[176]) }, [52] = { .gdb_size = 16, .gdb_offs = 468, FPU__(xmm_space[192]) }, [53] = { .gdb_size = 16, .gdb_offs = 484, FPU__(xmm_space[208]) }, [54] = { .gdb_size = 16, .gdb_offs = 500, FPU__(xmm_space[224]) }, [55] = { .gdb_size = 16, .gdb_offs = 516, FPU__(xmm_space[240]) }, [56] = { .gdb_size = 4, .gdb_offs = 532, FPU__(mxcsr) }, [57] = { .gdb_size = 8, .gdb_offs = 536, GEN__(orig_ax) }, }; #undef FPU__ #undef GEN__ static inline int rw_one_reg(struct task_struct *task, int regnum, unsigned char regval[], bool write) { const struct user_regset_view *view; const struct user_regset *rset; struct gdbreg *gdbreg; int err, count; view = task_user_regset_view(task); switch (view->e_machine) { case EM_X86_64: if (regnum >= ARRAY_SIZE(gdb_regmap_64)) return -EINVAL; gdbreg = gdb_regmap_64; count = sizeof(long); break; default: return -EIO; } gdbreg += regnum; rset = view->regsets + gdbreg->rs_setno; if (gdbreg->rs_setno != REGSET_GENERAL) count = gdbreg->gdb_size; if (WARN_ON(count > MAX_REG_SIZE)) return -EOVERFLOW; if (write) err = rset->set(task, rset, gdbreg->usr_offs, count, regval, NULL); else err = rset->get(task, rset, gdbreg->usr_offs, count, regval, NULL); return err ?: gdbreg->gdb_size; } static int ugdb_rw_one_reg(struct ugdb *ugdb, int regnum, unsigned char regval[], bool write) { struct utrace_examiner exam; struct task_struct *task; int ret = -ESRCH; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto ret; ret = rw_one_reg(task, regnum, regval, write); if (ugdb_finish_examine(ugdb, &exam)) ret = -ESRCH; ret: return ret; } // XXX: hex_to_bin() after 90378889 commit #include static int cap_hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; } static int unhex(char *cmd, int size) { char *bytes = cmd; while (size--) { int lo, hi; hi = cap_hex_to_bin(*cmd++); lo = cap_hex_to_bin(*cmd++); if (lo < 0 || hi < 0) return -EINVAL; *bytes++ = (hi << 4) | lo; } return 0; } static const char *handle_set_reg(struct ugdb *ugdb, char *cmd, int len) { unsigned int reg; int skip; if (sscanf(cmd, "P%x=%n", ®, &skip) != 1) goto err; cmd += skip; len -= skip; if (len & 1) goto err; len /= 2; if (unhex(cmd, len)) goto err; if (ugdb_rw_one_reg(ugdb, reg, cmd, true) != len) goto err; return "OK"; err: return "E01"; } static const char *handle_get_reg(struct ugdb *ugdb, char *cmd, int len) { unsigned char regval[MAX_REG_SIZE]; unsigned int reg; int skip, size; if (sscanf(cmd, "p%x%n", ®, &skip) != 1) goto err; if (len != skip) goto err; size = ugdb_rw_one_reg(ugdb, reg, regval, false); if (size < 0) goto err; pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, regval, size); pb_end(&ugdb->u_pbuf); return NULL; err: return "E01"; } static int rw_one_regset(struct task_struct *task, int rsn, const struct user_regset_view *view, void *reg_mem, int reg_size, struct gdbreg *reg_map, int reg_cnt, void *gdb_mem, bool write) { const struct user_regset *rset = view->regsets + rsn; int err; if (write) { for (; reg_cnt--; ++reg_map) { if (reg_map->rs_setno != rsn) continue; memcpy(reg_mem + reg_map->usr_offs, gdb_mem + reg_map->gdb_offs, reg_map->gdb_size); } err = rset->set(task, rset, 0, reg_size, reg_mem, NULL); } else { err = rset->get(task, rset, 0, reg_size, reg_mem, NULL); if (err) goto ret; for (; reg_cnt--; ++reg_map) { if (reg_map->rs_setno != rsn) continue; memcpy(gdb_mem + reg_map->gdb_offs, reg_mem + reg_map->usr_offs, reg_map->gdb_size); } } ret: return err; } #define GDB_REGS_SIZE(regmap) \ (regmap[ARRAY_SIZE(regmap)-1].gdb_size + \ regmap[ARRAY_SIZE(regmap)-1].gdb_offs) struct regs_buf { unsigned char gdb_mem[1024]; union { struct user_regs_struct user_regs_struct; struct user_i387_struct user_i387_struct; }; }; static int ugdb_rw_all_regs(struct task_struct *task, struct regs_buf *regs_buf, bool write) { const struct user_regset_view *view; int ret; #define RW(rsn, user, rmap) \ rw_one_regset(task, rsn, view, \ ®s_buf->user, sizeof(regs_buf->user), \ rmap, ARRAY_SIZE(rmap), regs_buf->gdb_mem, \ write) view = task_user_regset_view(task); switch (view->e_machine) { case EM_X86_64: ret = RW(REGSET_GENERAL, user_regs_struct, gdb_regmap_64); if (ret) break; // XXX: needs fixup if (!write) ret = RW(REGSET_FP, user_i387_struct, gdb_regmap_64); if (ret) break; ret = GDB_REGS_SIZE(gdb_regmap_64); break; default: ret = -EIO; } #undef RW return ret; } static const char *handle_get_all_regs(struct ugdb *ugdb) { struct regs_buf *regs_buf; struct utrace_examiner exam; struct task_struct *task; const char *ret = "E01"; int size; regs_buf = kzalloc(sizeof(*regs_buf), GFP_KERNEL); if (!regs_buf) goto out; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; size = ugdb_rw_all_regs(task, regs_buf, false); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (size < 0) goto err; if (size > sizeof(regs_buf->gdb_mem)) { WARN_ON(1); goto err; } if (pb_room(&ugdb->u_pbuf) < 3 + size * 2) { WARN_ON(1); goto err; } pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, regs_buf->gdb_mem, size); pb_end(&ugdb->u_pbuf); ret = NULL; err: kfree(regs_buf); out: return ret; } static const char *handle_set_all_regs(struct ugdb *ugdb, char *cmd, int len) { struct regs_buf *regs_buf; struct utrace_examiner exam; struct task_struct *task; const char *ret = "E01"; int size; printk(KERN_INFO "XXX: $G command, why?\n"); cmd += 1; len -= 1; if (len & 1) goto out; len /= 2; if (unhex(cmd, len)) goto out; regs_buf = kzalloc(sizeof(*regs_buf), GFP_KERNEL); if (!regs_buf) goto out; memcpy(regs_buf->gdb_mem, cmd, len); task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; size = ugdb_rw_all_regs(task, regs_buf, true); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (size < 0) goto err; WARN_ON(size != len); ret = "OK"; err: kfree(regs_buf); out: return ret; } static typeof(access_process_vm) *u_access_process_vm; static const char *handle_readmem(struct ugdb *ugdb, char *cmd) { struct utrace_examiner exam; struct task_struct *task; unsigned long addr, size; unsigned char *mbuf; int copied; if (sscanf(cmd, "m%lx,%lx", &addr, &size) != 2) goto err; mbuf = pb_alloc_bs(&ugdb->u_pbuf, size); if (!mbuf) { printk(KERN_INFO "XXX: apvm(%ld) ENOMEM\n", size); goto err; } task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; copied = u_access_process_vm(task, addr, mbuf, size, 0); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (copied > 0 ) { pb_start(&ugdb->u_pbuf); pb_putbs(&ugdb->u_pbuf, mbuf, size); pb_end(&ugdb->u_pbuf); return NULL; } err: return "E01"; } static const char *handle_writemem(struct ugdb *ugdb, char *cmd, int len) { unsigned long addr, size; unsigned int skip, written; struct utrace_examiner exam; struct task_struct *task; if (sscanf(cmd, "M%lx,%lx:%n", &addr, &size, &skip) != 2) goto err; cmd += skip; len -= skip; if (len != 2*size || !size) goto err; if (unhex(cmd, size)) goto err; task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto err; written = u_access_process_vm(task, addr, cmd, size, 1); if (ugdb_finish_examine(ugdb, &exam)) goto err; if (written == size) return "OK"; err: return "E01"; } static int ugdb_siginfo_rw(struct ugdb *ugdb, siginfo_t *info, bool write) { struct task_struct *task; struct utrace_examiner exam; struct sighand_struct *sighand; siginfo_t *t_siginfo; int ret = -EINVAL; /* * ugdb_prepare_examine() is overkill, but otherwise we can't * assume task_is_traced(), and this is what ensures we can * safely read/write ->t_siginfo which points to task's stack. */ task = ugdb_prepare_examine(ugdb, &exam); if (!task) goto out; /* OK, task_struct can't go away, but ->sighand can. */ rcu_read_lock(); sighand = rcu_dereference(task->sighand); if (!sighand) goto unlock_rcu; spin_lock_irq(&sighand->siglock); if (!task_is_traced(task)) goto unlock_siglock; t_siginfo = ugdb->u_cur_hg->t_siginfo; if (!t_siginfo) goto unlock_siglock; if (write) *t_siginfo = *info; else *info = *t_siginfo; ret = 0; unlock_siglock: spin_unlock_irq(&sighand->siglock); unlock_rcu: rcu_read_unlock(); ugdb_finish_examine(ugdb, &exam); out: return ret; } static const char *handle_siginfo_read(struct ugdb *ugdb, char *cmd) { unsigned int off, len; siginfo_t info; if (sscanf(cmd, "%x,%x", &off, &len) != 2) goto err; if (off >= sizeof(info)) goto err; if (len > sizeof(info) || off + len > sizeof(info)) len = sizeof(info) - off; if (ugdb_siginfo_rw(ugdb, &info, false)) goto err; if (pb_qfer(&ugdb->u_pbuf, &info + off, len, (off + len < sizeof(info)))) goto err; // XXX: Oh. we also need x86_siginfo_fixup(). how ugly. return NULL; err: return "E01"; } // ----------------------------------------------------------------------------- #define EQ(cmd, str) \ (strncmp((cmd), (str), sizeof(str)-1) ? false : \ ((cmd) += sizeof(str)-1, true)) static const char *handle_qfer(struct ugdb *ugdb, char *cmd) { const char *rc = "E01"; if (EQ(cmd, "siginfo:")) { if (EQ(cmd, "read::")) rc = handle_siginfo_read(ugdb, cmd); } return rc; } static void handle_command(struct ugdb *ugdb, char *cmd, int len) { struct pbuf *pb = &ugdb->u_pbuf; const char *rc = ""; switch (cmd[0]) { case '!': case '?': rc = "OK"; break; case 'H': rc = handle_set_cur(ugdb, cmd + 1); break; case 'T': rc = handle_ck_alive(ugdb, cmd + 1); break; case 'D': rc = handle_detach(ugdb, cmd + 1); break; case 'g': if (0) rc = handle_getregs(ugdb); else rc = handle_get_all_regs(ugdb); break; case 'G': rc = handle_set_all_regs(ugdb, cmd, len); break; case 'p': rc = handle_get_reg(ugdb, cmd, len); break; case 'P': rc = handle_set_reg(ugdb, cmd, len); break; case 'm': rc = handle_readmem(ugdb, cmd); break; case 'M': rc = handle_writemem(ugdb, cmd, len); break; case 'C': case 'c': case 'S': case 's': rc = handle_c(ugdb, cmd); break; case 'q': if (EQ(cmd, "qSupported")) { if (!strstr(cmd, "multiprocess+")) { printk(KERN_INFO "ugdb: can't work without multiprocess\n"); ugdb->u_err = -EPROTONOSUPPORT; } pb_packf(&ugdb->u_pbuf, "PacketSize=%x;%s", PACKET_SIZE, "QStartNoAckMode+;QNonStop+;multiprocess+;" "QPassSignals+;qXfer:siginfo:read+"); rc = NULL; } else if (EQ(cmd, "qfThreadInfo")) { rc = handle_thread_info(ugdb, true); } else if (EQ(cmd, "qsThreadInfo")) { rc = handle_thread_info(ugdb, false); } else if (EQ(cmd, "qXfer:")) { rc = handle_qfer(ugdb, cmd); } else if (EQ(cmd, "qTStatus")) { rc = "T0"; } break; case 'Q': if (EQ(cmd, "QStartNoAckMode")) { ugdb->u_no_ack = true; rc = "OK"; } else if (EQ(cmd, "QNonStop:")) { if (*cmd != '1') { printk(KERN_INFO "ugdb: all-stop is not implemented.\n"); ugdb->u_err = -EPROTONOSUPPORT; } rc = "OK"; } else if (EQ(cmd, "QPassSignals:")) { rc = handle_qpass_signals(ugdb, cmd); } break; case 'v': if (EQ(cmd, "vAttach;")) { rc = handle_vattach(ugdb, cmd); } else if (EQ(cmd, "vStopped")) { rc = handle_vstopped(ugdb); } else if (EQ(cmd, "vCont")) { rc = handle_vcont(ugdb, cmd); } break; default: ; } if (rc) pb_packs(pb, rc); } static void process_commands(struct ugdb *ugdb) { char *cmds = ugdb->u_cbuf; int todo = ugdb->u_clen; if (o_remote_debug) printk(KERN_INFO "=> %.*s\n", ugdb->u_clen, ugdb->u_cbuf); while (todo) { char first; char *c_cmd, *c_end; int c_len; first = *cmds++; todo--; switch (first) { default: printk(KERN_INFO "XXX: unknown chr %02x\n", first); pb_putc(&ugdb->u_pbuf, '-'); break; case '-': printk(KERN_INFO "XXX: got NACK!\n"); ugdb->u_err = -EPROTO; case '+': break; case 0x3: printk(KERN_INFO "XXX: unexpected CTRL-C\n"); break; case '$': c_cmd = cmds; c_end = strnchr(c_cmd, todo, '#'); c_len = c_end ? c_end - cmds : -1; if (c_len < 0 || todo < c_len + 3) { printk(KERN_INFO "XXX: can't find '#cs'\n"); ++todo; --cmds; goto out; } // XXX: verify checksum ? todo -= c_len + 3; cmds += c_len + 3; *c_end = 0; if (!ugdb->u_no_ack) pb_putc(&ugdb->u_pbuf, '+'); handle_command(ugdb, c_cmd, c_len); } } out: ugdb->u_clen = todo; if (todo && cmds > ugdb->u_cbuf) memmove(ugdb->u_cbuf, cmds, todo); } // ----------------------------------------------------------------------------- static int xxx_tinfo(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 0; mutex_lock(&ugdb->u_mutex); thread = ugdb_advance_tinfo(ugdb); if (thread) tid = thread->t_tid; mutex_unlock(&ugdb->u_mutex); return tid; } static int xxx_sc_threads(struct ugdb *ugdb, int tid, bool sc) { void *arg = NULL; int pid = 0; int ret; if (tid < 0) { pid = -tid; tid = -1; arg = (void*)1; } mutex_lock(&ugdb->u_mutex); ret = ugdb_do_each_thread(ugdb, pid, tid, sc ? do_stop_thread : do_cont_thread, arg); mutex_unlock(&ugdb->u_mutex); return ret; } static int xxx_stop(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, true); } static int xxx_cont(struct ugdb *ugdb, int tid) { return xxx_sc_threads(ugdb, tid, false); } static int xxx_get_stopped(struct ugdb *ugdb) { struct ugdb_thread *thread; int tid = 1; if (ugdb->u_stop_state == U_STOP_IDLE) return -1; if (ugdb->u_stop_state == U_STOP_PENDING) tid = 1000; thread = ugdb_next_stopped(ugdb); if (!thread) return 0; return tid * thread->t_tid; } static int xxx_show_all(struct ugdb *ugdb) { struct ugdb_process *process; struct ugdb_thread *thread; printk(KERN_INFO "SHOW start ----------------------------------------\n"); mutex_lock(&ugdb->u_mutex); list_for_each_entry(process, &ugdb->u_processes, p_processes) { printk(KERN_INFO "PROC: %x\n", process->p_pid); list_for_each_entry(thread, &process->p_threads, t_threads) { printk(KERN_INFO " T: %x %p; %p %p\n", thread->t_tid, thread, thread->t_spid, pid_task(thread->t_spid, PIDTYPE_PID)); } } mutex_unlock(&ugdb->u_mutex); printk(KERN_INFO "SHOW end ----------------------------------------\n"); return 0; } static long ugdb_f_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ugdb *ugdb = file->private_data; // XXX: otherwise gdb->get_tty_state(TCGETS, TCSETS, TCFLSH) complains int ret = 0; // XXX: temporary debugging hooks, ignore. switch (cmd) { case 0x666 + 0: ret = ugdb_attach(ugdb, arg); break; case 0x666 + 1: ret = ugdb_detach(ugdb, arg); break; case 0x666 + 2: ret = xxx_tinfo(ugdb); break; case 0x666 + 3: ret = xxx_stop(ugdb, arg); break; case 0x666 + 4: ret = xxx_cont(ugdb, arg); break; case 0x666 + 5: ret = xxx_get_stopped(ugdb); break; case 0x666 + 6: ret = xxx_show_all(ugdb); break; } return ret; } static unsigned int ugdb_f_poll(struct file *file, poll_table *wait) { struct ugdb *ugdb = file->private_data; unsigned int mask; poll_wait(file, &ugdb->u_wait, wait); mask = (POLLOUT | POLLWRNORM); if (pb_size(&ugdb->u_pbuf) || ugdb->u_stop_state == U_STOP_PENDING) mask |= (POLLIN | POLLRDNORM); if (ugdb->u_err) mask |= POLLERR; return mask; } static ssize_t ugdb_f_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; struct pbuf *pb = &ugdb->u_pbuf; if (ugdb->u_err) return ugdb->u_err; if (ugdb->u_stop_state == U_STOP_PENDING) ugdb_report_stopped(ugdb, true); if (pb_size(pb) > count) { printk(KERN_INFO "XXX: short read %d %ld\n", pb_size(pb), count); } return pb_copy_to_user(pb, ubuf, count); } static ssize_t ugdb_f_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct ugdb *ugdb = file->private_data; if (ugdb->u_err) return ugdb->u_err; if (count > PACKET_SIZE - ugdb->u_clen) { count = PACKET_SIZE - ugdb->u_clen; printk("XXX: write(%ld,%d) enospc\n", count, ugdb->u_clen); if (1) return ugdb->u_err = -ENOSPC; } if (copy_from_user(ugdb->u_cbuf + ugdb->u_clen, ubuf, count)) return -EFAULT; ugdb->u_clen += count; process_commands(ugdb); return count; } static int ugdb_f_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); file->private_data = ugdb_create(); return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; } static int ugdb_f_release(struct inode *inode, struct file *file) { ugdb_destroy(file->private_data); return 0; } static const struct file_operations ugdb_f_ops = { .open = ugdb_f_open, .unlocked_ioctl = ugdb_f_ioctl, .poll = ugdb_f_poll, .read = ugdb_f_read, .write = ugdb_f_write, .release = ugdb_f_release, }; #include struct kallsyms_sym { const char *name; unsigned long addr; }; static int kallsyms_on_each_symbol_cb(void *data, const char *name, struct module *mod, unsigned long addr) { struct kallsyms_sym *sym = data; if (strcmp(name, sym->name)) return 0; sym->addr = addr; return 1; } // XXX: kallsyms_lookup_name() is not exported in 2.6.32 static bool lookup_unexported(void) { struct kallsyms_sym sym; sym.name = "access_process_vm"; if (!kallsyms_on_each_symbol(kallsyms_on_each_symbol_cb, &sym)) goto err; u_access_process_vm = (void*)sym.addr; return true; err: printk(KERN_ERR "ugdb: can't lookup %s\n", sym.name); return false; } #define PROC_NAME "ugdb" struct proc_dir_entry *ugdb_pde; static int __init ugdb_init(void) { if (!lookup_unexported()) return -ESRCH; ugdb_pde = proc_create(PROC_NAME, S_IFREG|S_IRUGO|S_IWUGO, NULL, &ugdb_f_ops); if (!ugdb_pde) return -EBADF; return 0; } static void __exit ugdb_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(ugdb_init); module_exit(ugdb_exit);