From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21067 invoked by alias); 16 Dec 2014 21:24:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 20943 invoked by uid 89); 16 Dec 2014 21:24:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.3.2 X-HELO: usevmg21.ericsson.net Received: from usevmg21.ericsson.net (HELO usevmg21.ericsson.net) (198.24.6.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 16 Dec 2014 21:24:27 +0000 Received: from EUSAAHC004.ericsson.se (Unknown_Domain [147.117.188.84]) by usevmg21.ericsson.net (Symantec Mail Security) with SMTP id B2.53.25146.62640945; Tue, 16 Dec 2014 15:48:06 +0100 (CET) Received: from [142.133.110.254] (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.84) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 16 Dec 2014 16:24:24 -0500 Message-ID: <5490A306.3060002@ericsson.com> Date: Tue, 16 Dec 2014 21:24:00 -0000 From: Simon Marchi User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: Pedro Alves , Subject: Re: [PATCH 4/5] Linux: Skip thread_db thread event reporting if PTRACE_EVENT_CLONE is supported References: <1418748834-27545-1-git-send-email-palves@redhat.com> <1418748834-27545-5-git-send-email-palves@redhat.com> In-Reply-To: <1418748834-27545-5-git-send-email-palves@redhat.com> Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms080102040506020108070309" X-IsSubscribed: yes X-SW-Source: 2014-12/txt/msg00453.txt.bz2 --------------ms080102040506020108070309 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Content-length: 11743 On 2014-12-16 11:53 AM, Pedro Alves wrote: > [A test I wrote stumbled on a libthread_db issue related to thread > event breakpoints. See glibc PR17705: > [nptl_db: stale thread create/death events if debugger detaches] > https://sourceware.org/bugzilla/show_bug.cgi?id=3D17705 >=20 > This patch avoids that whole issue by making GDB stop using thread > event breakpoints in the first place, which is good for other reasons > as well, anyway.] >=20 > Before PTRACE_EVENT_CLONE (Linux 2.6), the only way to learn about new > threads in the inferior (to attach to them) or to learn about thread > exit was to coordinate with the inferior's glibc/runtime, using > libthread_db. That works by putting a breakpoint at a magic address > which is called when a new thread is spawned, or when a thread is > about to exit. When that breakpoint is hit, all threads are stopped, > and then GDB coordinates with libthread_db to read data structures out > of the inferior to learn about what happened. That is libthread_db's TD_CREATE event? Could you point out where that is done (stopping all the threads)? From the previous discussion with you, I was thinking that those breakpoints did not affect execution. I don't find any code in linux-thread-db.c that would do such a thing. > Then the breakpoint is > single-stepped, and then all threads are re-resumed. This isn't very > efficient (stops all threads) and is more fragile (inferior's thread > list in memory may be corrupt; libthread_db bugs, etc.) than ideal. >=20 > When the kernel supports PTRACE_EVENT_CLONE (which we already make use > of), there's really no need to use libthread_db's event reporting > mechanism to learn about new LWPs. And if the kernel supports that, > then we learn about LWP exits through regular WIFEXITED wait statuses, > so no need for the death event breakpoint either. >=20 > GDBserver has been likewise skipping the thread_db events for a long > while: > https://sourceware.org/ml/gdb-patches/2007-10/msg00547.html >=20 > There's one user-visible difference: we'll no longer print about > threads being created and exiting while the program is running, like: >=20 > [Thread 0x7ffff7dbb700 (LWP 30670) exited] > [New Thread 0x7ffff7db3700 (LWP 30671)] > [Thread 0x7ffff7dd3700 (LWP 30667) exited] > [New Thread 0x7ffff7dab700 (LWP 30672)] > [Thread 0x7ffff7db3700 (LWP 30671) exited] > [Thread 0x7ffff7dcb700 (LWP 30668) exited] >=20 > This is exactly the same behavior as when debugging against remote > targets / gdbserver. I actually think that's a good thing (and as > such have listed this in the local/remote parity wiki page a while > ago), as the printing slows down the inferior. It's also a > distraction to keep bothering the user about short-lived threads that > she won't be able to interact with anyway. Instead, the user (and > frontend) will be informed about new threads that currently exist in > the program when the program next stops: Is this a consequence of the change of algorithm, or did you actively chang= ed the behavior? >From what I understand, gdb still attaches to the new thread as soon as it= spawns (when it receives the PTRACE_EVENT_CLONE event), so it could print the noti= ce when the event happens. Not that I mind, but I just want to understand. > (gdb) c > ... > * ctrl-c * > [New Thread 0x7ffff7963700 (LWP 7797)] > [New Thread 0x7ffff796b700 (LWP 7796)] >=20 > Program received signal SIGINT, Interrupt. > [Switching to Thread 0x7ffff796b700 (LWP 7796)] > clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:81 > 81 testq %rax,%rax > (gdb) info threads >=20 > A couple of tests had assumptions on GDB thread numbers that no longer > hold. >=20 > Tested on x86_64 Fedora 20. >=20 > gdb/ > 2014-12-16 Pedro Alves >=20 > Skip enabling event reporting if the kernel supports > PTRACE_EVENT_CLONE. > * linux-thread-db.c: Include "nat/linux-ptrace.h". > (thread_db_use_events): New function. > (try_thread_db_load_1): Check thread_db_use_events before enabling > event reporting. > (update_thread_state): New function. > (attach_thread): Use it. Check thread_db_use_events before > enabling event reporting. > (thread_db_detach): Check thread_db_use_events before disabling > event reporting. > (find_new_threads_callback): Check thread_db_use_events before > enabling event reporting. Update the thread's state if not using > libthread_db events. >=20 > gdb/testsuite/ > 2014-12-16 Pedro Alves >=20 > * gdb.threads/fork-thread-pending.exp: Switch to the main thread > instead of to thread 2. > * gdb.threads/signal-command-multiple-signals-pending.c (main): > Add barrier around each pthread_create call instead of around all > calls. > * gdb.threads/signal-command-multiple-signals-pending.exp (test): > Set a break on thread_function and have the child threads hit it > one at at a time. > --- > gdb/linux-thread-db.c | 39 ++++++++++++++++= ++---- > gdb/testsuite/gdb.threads/fork-thread-pending.exp | 2 +- > .../signal-command-multiple-signals-pending.c | 11 +++--- > .../signal-command-multiple-signals-pending.exp | 7 ++++ > 4 files changed, 47 insertions(+), 12 deletions(-) >=20 > diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c > index 4b26984..35181f0 100644 > --- a/gdb/linux-thread-db.c > +++ b/gdb/linux-thread-db.c > @@ -38,6 +38,7 @@ > #include "observer.h" > #include "linux-nat.h" > #include "nat/linux-procfs.h" > +#include "nat/linux-ptrace.h" > #include "nat/linux-osdata.h" > #include "auto-load.h" > #include "cli/cli-utils.h" > @@ -77,6 +78,16 @@ static char *libthread_db_search_path; > by the "set auto-load libthread-db" command. */ > static int auto_load_thread_db =3D 1; >=20=20 > +/* Returns true if we need to use thread_db thread create/death event > + breakpoints to learn about threads. */ > + > +static int > +thread_db_use_events (void) > +{ > + /* Not necessary if the kernel supports clone events. */ > + return !linux_supports_traceclone (); > +} > + > /* "show" command for the auto_load_thread_db configuration variable. */ >=20=20 > static void > @@ -832,7 +843,7 @@ try_thread_db_load_1 (struct thread_db_info *info) > push_target (&thread_db_ops); >=20=20 > /* Enable event reporting, but not when debugging a core file. */ > - if (target_has_execution) > + if (target_has_execution && thread_db_use_events ()) > enable_thread_event_reporting (); >=20=20 > return 1; > @@ -1260,6 +1271,17 @@ thread_db_inferior_created (struct target_ops *tar= get, int from_tty) > check_for_thread_db (); > } >=20=20 > +/* Update the thread's state (what's displayed in "info threads"), > + from libthread_db thread state information. */ > + > +static void > +update_thread_state (struct private_thread_info *private, > + const td_thrinfo_t *ti_p) > +{ > + private->dying =3D (ti_p->ti_state =3D=3D TD_THR_UNKNOWN > + || ti_p->ti_state =3D=3D TD_THR_ZOMBIE); > +} > + > /* Attach to a new thread. This function is called when we receive a > TD_CREATE event or when we iterate over all threads and find one > that wasn't already in our list. Returns true on success. */ > @@ -1341,8 +1363,7 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *t= h_p, > gdb_assert (ti_p->ti_tid !=3D 0); > private->th =3D *th_p; > private->tid =3D ti_p->ti_tid; > - if (ti_p->ti_state =3D=3D TD_THR_UNKNOWN || ti_p->ti_state =3D=3D TD_T= HR_ZOMBIE) > - private->dying =3D 1; > + update_thread_state (private, ti_p); >=20=20 > /* Add the thread to GDB's thread list. */ > if (tp =3D=3D NULL) > @@ -1354,7 +1375,7 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *t= h_p, >=20=20 > /* Enable thread event reporting for this thread, except when > debugging a core file. */ > - if (target_has_execution) > + if (target_has_execution && thread_db_use_events ()) > { > err =3D info->td_thr_event_enable_p (th_p, 1); > if (err !=3D TD_OK) > @@ -1393,7 +1414,7 @@ thread_db_detach (struct target_ops *ops, const cha= r *args, int from_tty) >=20=20 > if (info) > { > - if (target_has_execution) > + if (target_has_execution && thread_db_use_events ()) > { > disable_thread_event_reporting (info); >=20=20 > @@ -1629,7 +1650,7 @@ find_new_threads_callback (const td_thrhandle_t *th= _p, void *data) > need this glibc bug workaround. */ > info->need_stale_parent_threads_check =3D 0; >=20=20 > - if (target_has_execution) > + if (target_has_execution && thread_db_use_events ()) > { > err =3D info->td_thr_event_enable_p (th_p, 1); > if (err !=3D TD_OK) > @@ -1666,6 +1687,12 @@ find_new_threads_callback (const td_thrhandle_t *t= h_p, void *data) > iteration: thread_db_find_new_threads_2 will retry. */ > return 1; > } > + else if (target_has_execution && !thread_db_use_events ()) > + { > + /* Need to update this if not using the libthread_db events > + (particularly, the TD_DEATH event). */ > + update_thread_state (tp->private, &ti); > + } >=20=20 > return 0; > } > diff --git a/gdb/testsuite/gdb.threads/fork-thread-pending.exp b/gdb/test= suite/gdb.threads/fork-thread-pending.exp > index 57e45c9..357cb9e 100644 > --- a/gdb/testsuite/gdb.threads/fork-thread-pending.exp > +++ b/gdb/testsuite/gdb.threads/fork-thread-pending.exp > @@ -46,7 +46,7 @@ gdb_test "continue" "Catchpoint.*" "1, get to the fork = event" >=20=20 > gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "1, m= ultiple threads found" >=20=20 > -gdb_test "thread 2" ".*" "1, switched away from event thread" > +gdb_test "thread 1" ".*" "1, switched away from event thread" >=20=20 > gdb_test "continue" "Not resuming.*" "1, refused to resume" >=20=20 > diff --git a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pe= nding.c b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending= .c > index 2fc5f53..761bef1 100644 > --- a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.c > +++ b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.c > @@ -76,12 +76,13 @@ main (void) > signal (SIGUSR1, handler_sigusr1); > signal (SIGUSR2, handler_sigusr2); >=20=20 > - pthread_barrier_init (&barrier, NULL, 3); > - > for (i =3D 0; i < 2; i++) > - pthread_create (&child_thread[i], NULL, thread_function, NULL); > - > - pthread_barrier_wait (&barrier); > + { > + pthread_barrier_init (&barrier, NULL, 2); > + pthread_create (&child_thread[i], NULL, thread_function, NULL); > + pthread_barrier_wait (&barrier); > + pthread_barrier_destroy (&barrier); > + } >=20=20 > all_threads_started (); >=20=20 > diff --git a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pe= nding.exp b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pendi= ng.exp > index b5ec00a..f574c57 100644 > --- a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.e= xp > +++ b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.e= xp > @@ -46,6 +46,13 @@ proc test { schedlock } { > gdb_test "handle SIGUSR2 stop print pass" >=20=20 > gdb_test "break all_threads_started" "Breakpoint .* at .*$srcfile.*" > + > + # Create threads one at a time, to insure stable thread > + # numbers between runs and targets. > + gdb_test "break thread_function" "Breakpoint .* at .*$srcfile.*" > + gdb_test "continue" "thread_function.*" "thread 2 created" > + gdb_test "continue" "thread_function.*" "thread 3 created" > + > gdb_test "continue" "all_threads_started.*" >=20=20 > # Using schedlock, let the main thread queue a signal for each >=20 --------------ms080102040506020108070309 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature Content-length: 5531 MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEH AQAAoIIMqjCCBewwggPUoAMCAQICEQCcTF8c4EKa6GVNC9lZ0VtfMA0GCSqG SIb3DQEBBQUAMDoxETAPBgNVBAoMCEVyaWNzc29uMSUwIwYDVQQDDBxFcmlj c3NvbiBOTCBJbmRpdmlkdWFsIENBIHYyMB4XDTE0MTIxNjE5NTk0NloXDTE3 MTIxNjE5NTk0NVowZjERMA8GA1UECgwIRXJpY3Nzb24xFTATBgNVBAMMDFNp bW9uIE1hcmNoaTEoMCYGCSqGSIb3DQEJARYZc2ltb24ubWFyY2hpQGVyaWNz c29uLmNvbTEQMA4GA1UEBRMHZW1haXNpbjCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAIUJ3Y1Kka6vwpVQ/RJWY5WcRchKpXoDaydFzm2o7BHE brgv8OuRtM7o9BOmZ2zKhIE8sqF6qieAB28IrELO+3GroV4sQw+lbs4LbjDI wU/DCKX1Y2Jeo+SGaKHMyJ6GPb/HNXrSG9toHjZVavEK1QsXKWmw5txx7i1w lG6iZrUGHT0n1zieZv+/kvoGLid2XITxQwN3qFWDhAv//1e+dWC+yuNiZf6T GagAvSto+Brt7G035UoLmj6TPuquQ6wGPe7NS7owTTTXO1QjRXGobL+SvUd8 fhPZnspi3GvGR6ez8lPLwwLmMR+EjE6eeRW3j+cWySwZHr6ElUXMxEXp3kMC AwEAAaOCAb8wggG7MEgGA1UdHwRBMD8wPaA7oDmGN2h0dHA6Ly9jcmwudHJ1 c3QudGVsaWEuY29tL2VyaWNzc29ubmxpbmRpdmlkdWFsY2F2Mi5jcmwwgYIG CCsGAQUFBwEBBHYwdDAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AyLnRydXN0 LnRlbGlhLmNvbTBIBggrBgEFBQcwAoY8aHR0cDovL2NhLnRydXN0LnRlbGlh c29uZXJhLmNvbS9lcmljc3Nvbm5saW5kaXZpZHVhbGNhdjIuY2VyMCQGA1Ud EQQdMBuBGXNpbW9uLm1hcmNoaUBlcmljc3Nvbi5jb20wVQYDVR0gBE4wTDBK BgwrBgEEAYIPAgMBARIwOjA4BggrBgEFBQcCARYsaHR0cHM6Ly9yZXBvc2l0 b3J5LnRydXN0LnRlbGlhc29uZXJhLmNvbS9DUFMwHQYDVR0lBBYwFAYIKwYB BQUHAwQGCCsGAQUFBwMCMB0GA1UdDgQWBBSkU7Li94HGv+OMwPr25KmDfTGr WDAfBgNVHSMEGDAWgBSxDcrURrevhgLDL28Gyg52cX9LNzAOBgNVHQ8BAf8E BAMCBaAwDQYJKoZIhvcNAQEFBQADggIBAA9Tk3HllgCdNwg47qHvOyoHBGLD kSOfkpt6JvcoHSDxZCPITq/Zh2jZbMFb/+Mx3dTU05vKxZEM/SD5PmYwEYZ7 6XYda92jpeJAcWwrO9ge1Es2jijoZ4B1Z/vvWCpSRMivyJgaLdWTvnINMb2V 1obTc0gLenubiyoHzbbS7mv7i17kB+e+Q/1Hn6avOsX0qVbO1aXnmOFAZ8Zh 8zsyy113BiTR19H22+PjKIfvWnnLaTqai7wO+mjMW62Ih2pTjC719bdt7tIy Al2trDCPxukzVzWpcV+ntMR/I7ucXB7e7NGa7raUZXI0wrwEx2iBQ9v2FNON SmdVBMyVioB1xMornioRqCY1vpihj9kkU1LfZHjRyW209g/tFuz+0B49Dish Kwhno3IFlWxvCH+yynnLzbbUF7kyYg4H02P9QZ6VqUAsDIAXZcb/sWLl1mKk 79NT5QEujbhVdbjpFX9g0JtgCMJHlS5MpydrYSlQ5zQNc0+XQ57OIYCQYCcE 2Dc6KTWNeTmyQIovNfM01X+GriF7A3dYszBR/kGQ5gQHs35/asND6I1mnJsQ 8F7rfOwbU8yQ/W+0JIzwBmX1i0P777x5txSglea9eRS3h1CRGMBobk7dbwQM Vvn4b1g8eBc95kTt3q3QrFhYoMWQJJIltWJpuwwP1mhbDEh0mWM7x5CmMIIG tjCCBJ6gAwIBAgIRAKAMy8ybmZjs4jpw9HzBwFkwDQYJKoZIhvcNAQEFBQAw NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJh IFJvb3QgQ0EgdjEwHhcNMTQwNTI3MDc0NjIxWhcNMjQwNTI3MDc0NjIxWjA6 MREwDwYDVQQKDAhFcmljc3NvbjElMCMGA1UEAwwcRXJpY3Nzb24gTkwgSW5k aXZpZHVhbCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ANq6U+tfSJZTn4k46qN13HgaeXXsMmGSWShc6A5IEyFboXMZW3lFHso+/6uO 3ZilvB2ipZJhrhU+RL/va+5Chay/PZq9ZZeE9N03OsHfOzlwk7uwojJ34tHL iX/yQoriI+b5DXxfIYXTFO5zlZLdaIxJwlLEQp0g4/zF6EGtodlpusaH07FA cLiIEeTMPRgXcn+8GoFOvtuVHNh/WHePlrupUgcI9/P54ITXvmZF6xcNBEjs u8yJm1VqqK0GXSgAmInJ4Ga8S6ME2wgSBRDolxAUbmfLQRrMvLC/tyXBvuLO 8uChdzpIWt3QPtMYm2R2V1Um0zANhenIUwYCKNPq5/yHaS48jCsOBAU0TIhB nirnZmlEbC6ALqwzGAcQMaMD8LFf1oLlWLUQxEmI4YXqBXdP5XnIcMdIEF5B tUBebzBJMMF9dDB2uj8BeoRPSYbpGl7irYUYFpq4TyocQ7qpHdYASC+NV8VT aTrFnHWqa/CGRdp3GHpkgxfOBvpamOK8udHQYQo2uA3YNd2+j7p4C3jkGG+Z 6RrZOskPEwtaIHLxBiA141dhCy5EScOyNajrAXQupsDnvr2ib2ef+4nObPFv edPWIe57lyj0n3e1rTqTGIBIe9wjNnAA6MqeaTS9HchPtBvOrah/cTWzXzGj wMz0P3UJqTQ2r5EAu12/W5kpAgMBAAGjggG4MIIBtDCBigYIKwYBBQUHAQEE fjB8MC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC50cnVzdC50ZWxpYXNvbmVy YS5jb20wSwYIKwYBBQUHMAKGP2h0dHA6Ly9yZXBvc2l0b3J5LnRydXN0LnRl bGlhc29uZXJhLmNvbS90ZWxpYXNvbmVyYXJvb3RjYXYxLmNlcjASBgNVHRMB Af8ECDAGAQH/AgEAMFUGA1UdIAROMEwwSgYMKwYBBAGCDwIDAQECMDowOAYI KwYBBQUHAgEWLGh0dHBzOi8vcmVwb3NpdG9yeS50cnVzdC50ZWxpYXNvbmVy YS5jb20vQ1BTMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwtMy50cnVz dC50ZWxpYXNvbmVyYS5jb20vdGVsaWFzb25lcmFyb290Y2F2MS5jcmwwHQYD VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA4GA1UdDwEB/wQEAwIBBjAd BgNVHQ4EFgQUsQ3K1Ea3r4YCwy9vBsoOdnF/SzcwHwYDVR0jBBgwFoAU8I9Z OACz9Y+algzV6/p7qhfoExIwDQYJKoZIhvcNAQEFBQADggIBAG4HIGyvrHc9 kEKyYZtxJn9cv7S2dUxuUiegmAvUGHc+JGJyB2jyX7py9an8CsHAxg3BI3Ku 9j0h7DJpXyfrlzmg36XYkNS7Ot0A1UqdjGFrtnIISI+Zj3ywHZudmDF8ktdB ihHAjuk47B/Kg/Z8JhUJ37GGx/KxiIiXg5HMTdOl6mlDbJaTIEGagdRcmH3u 57r5snZ+qdVSg5UxWdhgS2+zPru/vDbPd+91zLTj9GejKXFJ6fEAOLW1j2Ij J0cyDI67d1/OzFTwCK8wYbhopK2wJ9QTKDQuWRuGoyt2d6yzd7WoAS55JE0B It+kXDJGbOaK42H2ifO6ERHbJiEr/oh4KzgdAes+GRjwlSaG2Z0va4Ss5lY6 zfwVCEZYdZcjSDpKB0M5tTQYQeO7QyQPOI6Gb4FXA9ko3sHvAPs4+Pq+UtWj p3y8sYr1vLCER9ePEsgLdCG27mUk9OAijkG6n5oEGOIn+70F+qvKpmm52dZ8 b7DELfbuuk0CrY4p0WxH3bBt6FJkPeZJIB6YNXAYHZi7RcdBjLJh+lawbIYT JFIcoWFHAl0g0/NYsjz3DLhZz4+CrJ6SQSYmp7qDhdJAWPiaq3C+qE/h2DZA Jwoz9uHrZHB8zsZ5JL8sUZ7zgqYmNMN+9PxzasrycTJn96Y63AIZdDq1kIHI w0vF4PBTVMZtMYIDBzCCAwMCAQEwTzA6MREwDwYDVQQKDAhFcmljc3NvbjEl MCMGA1UEAwwcRXJpY3Nzb24gTkwgSW5kaXZpZHVhbCBDQSB2MgIRAJxMXxzg QproZU0L2VnRW18wCQYFKw4DAhoFAKCCAY0wGAYJKoZIhvcNAQkDMQsGCSqG SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQxMjE2MjEyNDIyWjAjBgkqhkiG 9w0BCQQxFgQUHzFapC34/YejaEXln6qZiIkNUYwwXgYJKwYBBAGCNxAEMVEw TzA6MREwDwYDVQQKDAhFcmljc3NvbjElMCMGA1UEAwwcRXJpY3Nzb24gTkwg SW5kaXZpZHVhbCBDQSB2MgIRAJxMXxzgQproZU0L2VnRW18wYAYLKoZIhvcN AQkQAgsxUaBPMDoxETAPBgNVBAoMCEVyaWNzc29uMSUwIwYDVQQDDBxFcmlj c3NvbiBOTCBJbmRpdmlkdWFsIENBIHYyAhEAnExfHOBCmuhlTQvZWdFbXzBs BgkqhkiG9w0BCQ8xXzBdMAsGCWCGSAFlAwQBKjALBglghkgBZQMEAQIwCgYI KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAARBAqZ3OTbV 0Rq1CTwB5/77/8/8dvYLCtU4cUP/RC05Kc+PEEUtso7cmbIGZxwMtCkQao+H f5Q637pDrY/qR44XTnRGPnDMom4HDY3c5jssBFIpw8YuMPFBAgGYbdXJyXCl T/kBYOSzppoVTie1mGSZC2rVqOJcjnIhjGp/0hsxGCyZGusHuefwspSu8YGr dJ26pxSR82RUil14eWg8G2RYNkfkR0a01tgrYunR7o1BvJlprU38BQJYPAMt 53dwup3j8yKde+tyb1ZIR7WEioU3G+DWA0c8jvhSi50LXoFVn08BI/EZ1bK0 t76yjkzbNHif0fBeMiJ7bXAW3DCOrFsAAAAAAAA= --------------ms080102040506020108070309--