ftp.delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-apps/2002/04/26/16:38:58

Mailing-List: contact cygwin-apps-help AT cygwin DOT com; run by ezmlm
Sender: cygwin-apps-owner AT cygwin DOT com
List-Subscribe: <mailto:cygwin-apps-subscribe AT cygwin DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin-apps/>
List-Post: <mailto:cygwin-apps AT cygwin DOT com>
List-Help: <mailto:cygwin-apps-help AT cygwin DOT com>, <http://sources.redhat.com/lists.html#faqs>
Mail-Followup-To: cygwin-apps AT cygwin DOT com
Delivered-To: mailing list cygwin-apps AT cygwin DOT com
Reply-To: <kde-cygwin AT mail DOT kde DOT org>
From: "Ralf Habacker" <Ralf DOT Habacker AT freenet DOT de>
To: "Kde-Cygwin" <kde-cygwin AT kde DOT org>,
"Binutils" <binutils AT sources DOT redhat DOT com>,
"Cygwin-Apps" <cygwin-apps AT cygwin DOT com>
Subject: ordinal linking for cygwin ld
Date: Fri, 26 Apr 2002 22:35:45 +0200
Message-ID: <00db01c1eb76$239e4dd0$651c440a@BRAMSCHE>
MIME-Version: 1.0
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
Importance: Normal
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
X-Spam-Rating: max.tat.physik.uni-tuebingen.de 400/1000/N
X-Reply-To: kde-cygwin AT mail DOT kde DOT org
Note-from-DJ: This may be spam

This is a multi-part message in MIME format.

------=_NextPart_000_0053_01C1ED72.B55A6760
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hi all,

one of the biggest problems with kde 2.2.x currently is the very bad loading
time of applications and dll's, I've investigated some time to analyse this. On
this way I recognized, that runtime linking using symbol names is one of the
major time eater.

At first I have tried to estimate the influence of symbol name to the runtime
linking time. So I have build a dll 5000 functions and a client app, which uses
this functions.

This dll/apps are compiled in two variants, 1. with a symbolname lenght of a 13
characters and 2. with a symbolname lenght of 403 characters (should simulate
long c++ names).

cd shortname
time ./client.exe
real    0m0.772s
user    0m0.030s
sys     0m0.030s

$ cd longname
$ time ./client.exe
real    0m15.182s
user    0m0.060s
sys     0m0.040s

The result shows that this has a great effect of app/dll loading time (about 20
times more).

After thinking a while about this, I remembered, that the windows pe format
allows two runtime linking types. The first, usually used, is linking by the
symbol name, the second is linking by symbols ordinal.

A look in the last official cygwin ld (20011002) source shows, that linking by
ordinal seems to be prepared with one limitation.
There is no command line switch to create an import library for ordinal linking
on dll building, so I've added a switch --out-implib-ordinal <filename>.

(BTW: Another possibibily was automatic ordinal linking. See later)

Now I've tried a second test. 5000 functions with symbolname lenght of 403
characters linked 1. with names and 2. with ordinals.

5000 functions with symbol name linking (symbols not stripped)

$ time ./client.exe
real    0m15.182s
user    0m0.060s
sys     0m0.040s

5000 functions with ordinal linking (symbols not stripped)

$ time ./client.exe
real    0m0.572s
user    0m0.020s
sys     0m0.030s

Wow, thats great.

1. Currently I' have a working solution for binutils 20011002 using a specific
import library create with an -out-implib-ordinal option, which contains only
ordinals and no symbols in the IMPORT_DESCRIPTOR_BY_NAME structure. (The patches
and testcase are appended)

2. Another possibility is using the regular import libraries hint number for
ordinal linking (hint number = Ordinal number-1), but currently I don't know if
this is always true.

Solution 1 has an advantage on building big c++ libs, because the import library
are smaller (about 20-50%). See the following example. The amount depends on the
symbols count and length.

old
-rwxr-xr-x    1 1002     Kein      1682944 Apr 22 09:42
/opt/kde2/bin/cygkdecore-3.dll
-rwxr-xr-x    1 1002     Kein      3190016 Apr 20 19:12
/opt/kde2/lib/libkdecore.dll.a

new
-rwxrwxrwx    1 1002     Kein      1956812 Apr 26 22:03 libkdecore.dll.a
-rwxrwxrwx    1 1002     Kein      1608192 Apr 26 22:28 cygkdecore-3.dll

Solution 2 is full compatible to dll's builded with previous ld, because the dll
and import lib are still the same. Compiling an app with new ld will
automatically use ordinal linking. The only necessary point seems to me a
command line switch to switch of this behavior.

Any comments ?

Regards
Ralf


------=_NextPart_000_0053_01C1ED72.B55A6760
Content-Type: application/octet-stream;
	name="ld_ordinal_linking_2.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ld_ordinal_linking_2.patch"

--- pe-dll.c.orig	Fri Apr 26 17:23:34 2002=0A=
+++ pe-dll.c	Fri Apr 26 21:55:42 2002=0A=
@@ -120,6 +120,8 @@=0A=
 =0A=
     See also: ld/emultempl/pe.em.  */=0A=
 =0A=
+extern int pe_implib_ordinal;
+
 static void=0A=
 add_bfd_to_link PARAMS ((bfd *, const char *, struct bfd_link_info *));=0A=
 =0A=
@@ -1895,6 +1897,8 @@ make_one (exp, parent)=0A=
   return abfd;=0A=
 }=0A=
 =0A=
+extern long pe_data_import_ordinal;
+
 static bfd *=0A=
 make_singleton_name_thunk (import, parent)=0A=
      const char *import;=0A=
@@ -1927,6 +1931,14 @@ make_singleton_name_thunk (import, paren=0A=
   d4 =3D (unsigned char *) xmalloc (4);=0A=
   id4->contents =3D d4;=0A=
   memset (d4, 0, 8);=0A=
+ =20
+  /* handle ordinal linking */=20
+  if (pe_data_import_ordinal) {
+    d4[0]=3D pe_data_import_ordinal;
+    d4[1]=3D pe_data_import_ordinal>>8;
+    d4[3]=3D 0x80;
+  }
+  else=20
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);=0A=
   save_relocs (id4);=0A=
 =0A=
@@ -2121,6 +2133,10 @@ pe_dll_generate_implib (def, impfilename=0A=
       bfd *n;=0A=
 =0A=
       def->exports[i].internal_name =3D def->exports[i].name;=0A=
+
+      if (pe_implib_ordinal) {
+         def->exports[i].flag_noname =3D 1;
+      }
       n =3D make_one (def->exports + i, outarch);=0A=
       n->next =3D head;=0A=
       head =3D n;=0A=
--- emultempl/pe.em.orig	Tue Apr 23 13:47:55 2002=0A=
+++ emultempl/pe.em	Fri Apr 26 22:20:13 2002=0A=
@@ -153,6 +153,7 @@ static char *pe_out_def_filename =3D NULL;=0A=
 static char *pe_implib_filename =3D NULL;=0A=
 static int pe_enable_auto_image_base =3D 0;=0A=
 static char *pe_dll_search_prefix =3D NULL;=0A=
+int pe_implib_ordinal =3D 0;
 #endif=0A=
 =0A=
 extern const char *output_filename;=0A=
@@ -221,6 +222,7 @@ gld_${EMULATION_NAME}_before_parse()=0A=
 #define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)=0A=
 #define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + =
1)=0A=
 #define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + =
1)=0A=
+#define OPTION_IMPLIB_ORDINAL		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
 =0A=
 static struct option longopts[] =3D {=0A=
   /* PE options */=0A=
@@ -252,6 +254,7 @@ static struct option longopts[] =3D {=0A=
   {"enable-stdcall-fixup", no_argument, NULL, =
OPTION_ENABLE_STDCALL_FIXUP},=0A=
   {"disable-stdcall-fixup", no_argument, NULL, =
OPTION_DISABLE_STDCALL_FIXUP},=0A=
   {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},=0A=
+  {"out-implib-ordinal", required_argument, NULL, =
OPTION_IMPLIB_ORDINAL},
   {"warn-duplicate-exports", no_argument, NULL, =
OPTION_WARN_DUPLICATE_EXPORTS},=0A=
   {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},=0A=
   {"enable-auto-image-base", no_argument, NULL, =
OPTION_ENABLE_AUTO_IMAGE_BASE},=0A=
@@ -336,6 +339,8 @@ gld_${EMULATION_NAME}_list_options (file=0A=
   fprintf (file, _("  --export-all-symbols               Automatically =
export all globals to DLL\n"));=0A=
   fprintf (file, _("  --kill-at                          Remove @nn =
from exported symbols\n"));=0A=
   fprintf (file, _("  --out-implib <file>                Generate =
import library\n"));=0A=
+  fprintf (file, _("  --out-implib-ordinal <file>        Generate =
import library using ordinals \n"));
+  fprintf (file, _("                                       instead of =
names\n"));
   fprintf (file, _("  --output-def <file>                Generate a =
.DEF file for the built DLL\n"));=0A=
   fprintf (file, _("  --warn-duplicate-exports           Warn about =
duplicate exports.\n"));=0A=
   fprintf (file, _("  --compat-implib                    Create =
backward compatible import libs;\n"));=0A=
@@ -630,6 +635,10 @@ gld_${EMULATION_NAME}_parse_args(argc, a=0A=
     case OPTION_ENABLE_EXTRA_PE_DEBUG:=0A=
       pe_dll_extra_pe_debug =3D 1;=0A=
       break;=0A=
+    case OPTION_IMPLIB_ORDINAL:
+      pe_implib_filename =3D xstrdup (optarg);
+      pe_implib_ordinal =3D 1;
+      break;
 #endif=0A=
     }=0A=
   return 1;=0A=
@@ -885,6 +894,57 @@ make_import_fixup (rel, s)=0A=
 =0A=
   return 1;=0A=
 }=0A=
+void get_data_import_ordinal(bfd *b)
+{
+	struct sec *s =3D bfd_get_section_by_name (b, ".idata$5");
+	if (s)
+	{
+	  int size =3D bfd_get_section_size_before_reloc (s);
+	  char *buf =3D xmalloc (size);
+=09
+	  bfd_get_section_contents (b, s, buf, 0, size);
+	  pe_data_import_ordinal =3D *(unsigned short *)buf;
+	  if (pe_dll_extra_pe_debug)
+	    printf("#%04x\n",pe_data_import_ordinal);
+	  free (buf);
+	}
+	else=20
+	  pe_data_import_ordinal =3D 0;
+}
+
+
+/* ordinal linking=20
+
+ordinal import library object file=20
+
+d001500.o:     file format pe-i386
+
+Contents of section .idata$7:
+ 0000 00000000                             ....
+Contents of section .idata$5:
+ 0000 dc050080                             ....
+      ^^^^^
+  This value is used=20
+     =20
+Contents of section .idata$4:
+ 0000 dc050080                             ....
+
+
+regular import library object file=20
+
+d001500.o:     file format pe-i386
+
+Contents of section .idata$7:
+ 0000 00000000                             ....
+Contents of section .idata$5:
+ 0000 00000000                             ....
+Contents of section .idata$4:
+ 0000 00000000                             ....
+Contents of section .idata$6:
+ 0000 db057661 72303439 39000000           ..var0499...
+      ^^^^
+      This value seems also be usable (not implemented yet)
+*/
 =0A=
 static void=0A=
 pe_find_data_imports ()=0A=
@@ -916,6 +976,8 @@ pe_find_data_imports ()=0A=
                 symbols =3D (asymbol **) xmalloc (symsize);=0A=
                 nsyms =3D bfd_canonicalize_symtab (b, symbols);=0A=
 =0A=
+		get_data_import_ordinal(b);
+
                 for (i =3D 0; i < nsyms; i++)=0A=
                   {=0A=
                     if (memcmp(symbols[i]->name, "__head_",=0A=

------=_NextPart_000_0053_01C1ED72.B55A6760
Content-Type: application/octet-stream;
	name="ld_ordinal_linking_testcase.tar.bz2"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
	filename="ld_ordinal_linking_testcase.tar.bz2"

QlpoOTFBWSZTWaWFVUkAO/z/hOwyEAJef///f///9f//3/4AAIAIYCdB9CgeAAAUAAAmwg0AAAoB
gfAAICAAgIABAgAECwBgQAgQAgIAgIAgAOgBAaAAAAiiImRoammTSekaT1M0mNU8KPSepgxQYnqB
4aE2mpqek9Q5k00MgAYjIMgBpggYgGjTQAZA0AHMmmhkADEZBkANMEDEA0aaADIGgAip+hof6qKq
npA/1UNAAAAyANANAAAAAMNVU/36mpVSb//TVKqNAAAAAAAAAAAAAAIp/6qaU022qqVNP1Q9Rk0A
f6qMgNAAAMgAAAAFl4fn5/RPz3BbPOETAARcoLycfJGYu64UD6UiytaTbGQQYC5OCATUBMxDBLMB
AEQgQEQwhMJMRAQgwTBMQEMb//oQQO721BVmP2qqCrSILZiqaYsWJNe6Sa22Out/19Fb0zyyuvW+
u7re9eu/Lrt1/s978r8vfavdO+GlLSsTSzPhfk9Xt3X2+nnimGM4Od0YJXCQmF5Yu4EqtQg06P0M
YxMD5dOuA+iLb9f15csc2fpCE1QbGh8DIG56DoARV0JjZYb5VkvI9xQPuLi3SZyQzidO3f5ct3W0
37g+OgwsLdfjMm8dQ6wbkdHCJlYE4P1bqunuq1Va1RXnfy+nUp96r8D0r6FfRdfc/W+n6/E+NX9X
Ssb1CMvkSTVmyYajjBO1q1Rc2GJ2kNRKZBEVbd+IQRVyI2b1nqOc/Ex4ge1cXiKrvardab2T34rZ
D6IsNiCKvNDvbNxzVzEBZToPId0/OFoQAiruM8Q3VH8t69yJtI8qTMiIq2kSEkhKd8CDeSJ1EfMm
oVUyG540h7xHmLA5jrCIq5OOQRVex1A4PMNQuDAIEtsIfX+tE/S/D+L1vW+1+P8m0gGiwDIuBQYB
gFBcDIsA0SAbQAGkLANpANFgGRcCgwDAKC4GRYBokA2gAMoLgbSAaLAMi4FBgGAUFwMiwDRIBtAA
UgYBtIBosAyLgUGAYBQXAyLANEgG0ABhAUG0gGiwDIuBQYBgFBcDIsA0SAbQAF0AyNpANFgGRcCg
wDAKC4GRYBokA2gALIA0bSAaLAMi4FBgGAUFwMiwDRIBtAASgBttIBosAyLgUGAYBQXAyLANEgG0
ABCABtIBosAyLgUGAYBQXAyLANEgG0AC/i3w6DvkUKB+AmKV+wbIYhxxxxxxxxxxvvvvvvvvAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAD38elHomIjxHjx48efEGKnfxErS08QQKirXvxMEB8ay8zeviyTH96zQOE/jJ3ocuQ/lB2
PWWHd0Hngg7cmEFJkJgZiddaqq+XV1qr0rT1+VX7lfzfWrKr4/FV18Gvj4+Pj4+Pj3zmuAZFwKDA
MAoLgZFgGiQDaAA98AOAAAAAAAAAAAAAAAYnxAMje9+eeeeecrr6/3n16rSqrWgAB8uq3aqvQAGq
rWhqtaAAA1WtAAAarWgAANVrQAAGq1oAADVa0AXrQ3dVdjda0AABqtaAAA1fywwrhZZZZYFIrNa2
YYYYXXXXXXXXXX5oDDw/V09OOSItmZnQAPda0AABqtaAAA1WtAAAarWgAANVrQAAGq1oAADVa0AN
VWtANVrQAAGq1oAADXz+fz+d73ve973v5/P5/P58888888885IAABqtaAAA1WtAAAarWgAANVrQA
AGq1oAADVa0AABqtaJrQABda0AABqtaAAA1cku973ve97kknOeeeeeeeckAAA1WtAAAa9rsAADVa
0AABqtaAAA1WtAAAarWgAANVrRNaAALrWgAANVrQAAGrkl3e973ve/cknOc8888885IAABqtaAAA
1WtAAAarWgAANVrQAAGq1oAADVa0AABr2uwAANVrQAAGq1oAADUkl3d7+xVVXr169evPl8vl8uc5
zzzzzznyrqoIEggSCBIIEggSCBIIEggSBXVMzMu7vfnr169Z3nvM5znOeeeecyuqUrqlK6pSuqUr
qlK6pSuqUrqlK6pSuqZmZd3e973vM7zM5znOc8885ldUpXVKV1SldUp119tVOtdK6pSuqUK6VTpS
uqUrqkkl3d73ve5J7k5znOc555zK6pSuqUrqlK6pSuqUrqlK6pSuqUrqlK6pmZl3d73ve8zM8znO
c5znPOZXVKV1SldUpXVKV1SldUpXVKV1SldUpXVMzMu7vf4Pr169SSTOc5znOc5znAAAABzkeY8R
PY73ve971tIBosAyLgxjGMPHhAA2kA0WAZFwKDAMAoLgZFgGiQDfkAcAAAAAAAAAAAAAAAAHASSb
tPQl5xYCOHEcOIBAIBAIBAc888862222/PPPPLJJJJN2iAQCAQCAQCAQCA5bbnW2227bbdkkkk3a
IBAIBHpZiwEAgEAgOW251tttu+nbbskkkm7RAIBAIBAIBAIBActtzrbbbdttuySSSbtEAgEAgEAg
EAgEBy23Otttt2227JJJJu+mriwEAgEAgEfkzFgIBAc889LzOtttt+eeeeXZJJJN2iAQCAQCAQCP
y5iwEBzzzzzOtttt+eeeeXZJJJN2iAQCAQCOJHEAgEAgOW251tttu223ZJJJN2iAQCAQCAQCAQCA
5bbnW2227bbdkkkk3aIBAIBAIBAIBAIDltudbfaxjHe973gAAAAAA9LnI5znOc5xBAA2kA0WBjGM
YtGIjM/+5yOVzPN84ggAbSAaLAMi4FBgGAUFwMiwDXoAHAAAAAAAAAAAAAAAX2DI5wA5z0W/RN72
i1rRa1otayAQCAQCA55555nW222/PPPPLskkkm7RAIBAIBAIBAIBActtzrbbbdttuySSSbtEAgEA
gEAgEAgEBy23M62227bbd2SSSbtEeksxYCMzFgIBAIBAIDltuZ1ttt307bd2SSSbtEAgEAgEAgEX
MWAgOZbczrbbbttt3ZJJJu0QCAQCAQCAQCAQHLbczrbbbttt3ZJJJu0QCAQCAQCAQCAQHLbczrbb
bttt3ZJJJu0QHoAQCAQCAQCAQHLbczrbbbttt3ZJJJu0QCAQCAQCAQCAQHLbczrbbbttt3ZJJJu0
QCAQCAQCAQCAi1rT3ve3vWMVVYx3ve94AAAAAABIBtABAgAbSDGMYwJANoAIEADaQDRYBkXAoMAw
CguBnoA4AAAAAAAAAAAAAADewDnOAOc7aLWtFrWi1rIBAIBAIBActtzOtttu223dkkkm7RAIBAIB
GrMWAgEAgOV25nWxsbttt3ZJJJu0QCAQCAQCAQCAQHLbczrbbbttt3ZJJJu0QCAQCNzFgIBAIBAc
rtzM6223bbbu7JJJu0QCAQCARMxYCAQCA5b25mdbbbttt3dkkk3aIBAIBAIBAIBAIDltuZnW227b
bd3ZJJN2iAQCAQCAQCAQCA5bbmZ1ttu223d2SSTdogPQAgEAgEAgEAgOW25mdbbbttt3dkkk3aIB
AIBAIBAIBAIDltuZnW227bbd3ZJJN2iAQCAQCAQCAQCA5bbmZ1973rttuySSSSSSSSSAAAAsA0SA
bQAgIBjGMYCwDRIBtACAgAbSAaLAMi4FBgGAV0AcAAAAAAAAAAAAAABvewHOc4BznbRa1otYQCAQ
CAQCAQHLbczOttt2227uySSbtEAgEAgEAgEAgEBy23Mzrbbdttu7skkm7RAIBAIBAIBAIBActtzM
6223bbbu7JJJu0QCAQCAQCAQCAQHLbczOttt2227uySSbtEAgEAgEAgEAgEBy23MzO3ve972227u
7JJN2iAQCARMxYCAQCAQHLe3MzOttu223d3ZJJu0R3MWZ6MxYCAQCAQCAQHLbczM6m23bLbu7skk
3aIBAIBAI9TMWXMWAgEBzx+eZmZ1tt+eeeeXd3ZJJu0QCAQCAQCAQCAQHLbczM6227bbd3dkkm7R
AIBAIBAIBAIBActtzMzve972227JJJJJIAAAAAXAyLANEgG0AVVVVRERfNhi5oZFgGiQDaAIBAA2
kA0WAZFwKDHQBwAAAAAAAAAAAAAAG972BznOcSSbvqBznOUAOc5znOc8zzzzMzPSbbfnnnnl3czn
Oc5mAAASSS7u++dV69evXqT3JMzM5znOZgAAEkku7vve973JJJmZnOc5zMAAAkkl3d973ve5JJMz
M5znOZgB71oAkk7u7vve973JJJmZnOc5zMAAAkkl3d973vc9SSTMzM5znMwADNaCXJLu773ve56k
kmZmZznOZgAAEkku7vve97nqSSZmZnOc5mAAASSS7u+973uepJJmZmc5zmYAABJJLu779evXr1JO
94AAAAAAAMAoLgZFgGiQpVVWLyDDQoLgZFgGiQDaAQBAA2kA0WAZF+gDgAAAAAAAAAAAAAAN73vb
nOczMzM5znLzAAAJJJd3fe973PXkkmZmZznOZge9aAAkk7u7vve97nqSSZmZnOc5rMA99a0AEknd
3d973vc9TkkzMzOc5zMAAAkkl3d973vc9SSTMzM5znMwAACSSXd33ve9z1JJMzMznOczAAAJJJd3
fe973PUkkzMzOc5zM71oAAJJJd3fe9737nckmZmZnOczAAzWgJcku7vve97k7kkzMzM5zmYAABJJ
Lu773ve5O5JMzMzOc5mAAASSS7u81VVXe973gAAAAAAAUGAYBQXAyLCqVVWiM4GCtDAMAoLgZFgG
iQDaAgBAA2kA0W6AOAAAAAAAAAAAAAAc5znPPPPPPOc5zMzMzOc5mABvWgJJJd3fe973J3ySZmZm
c5zMAAAkkl3d96vbW5O5JMzMzOc5mAAASSS7u+973uTuSTMzMznOZgAAEkku7vve97k7kkzMzM5z
mYAA6oEkku7vut73uTuSTMzMznOZhlV5dgAE3J3d3feevXr1PXckmZmZnOczA960ABJJ3d3ffKr1
69epPfuSZmZmc5zMUAB1QJJJd3fe973JPckzMzMznMwAACSSXd33ve9yT3JMzMzM5zMBMzMzMzMz
Pe972973zVVVd73veAAAAAAAAyLgUGAYBQXKqlVYBkXAoMAwCguBkWAaJANoEAEADaegDgAAAAAA
AAAAAAAAN73ve9jnOc5znDnJmZkABJJLu773ve5J7kmZmZmc5mAAASSS7u+973uSe5JmZmZnOZgA
AEkku7vve97knuSZmZmZzmYAABJJLu773ve5J7kmZmZmc5mAAASSS7u+973uSe5JmZmZnOZgAAEk
ku7vve97knuSZmZmZzmYAABJJLu773ve5J7kmZmZmc5mAAASSS7u+973uSe5JmZmZnOZgAAEkku7
vve97kk8kzMzMzOZgJmZmZmZmZ73ve3ve+aqqrve97wAAAAAAADRYBkXAoMAwqqpUgGiwDIuBQYB
gFBcDIsA0SAbQQAI6AOAAAAAAAAAAAAAAA3ve973s5znOc5zjnJmZkABJJLu773ve5JPJMzMzMzm
YAABJJLu773ve5JPJMzMzMzmYAABJJLu773ve5JPJMzMzMzmYAABJJLu773ve5JPJMzMzMzmYAAB
JJLu773ve5JPJMzMzMzmYAABJJLu773ve5JPJMzMzMzmYAABJJLu773ve5JPJMzMzMzmYAABJJLu
773ve5JPJMzMzMzmYAABJJLu773ve5JPJMzMzMzmYCZmZmZmZme973t73vmqqq73ve8AAAAAAAAb
SAaLAMi4FVVVT3fwPT9n6/yo9z8X4nj6fr98+fPnz58+fIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfMjxHPnWmfE+LQOwSgCKvBnks
TwSeCNqP8IQdp4rWvJmwza9fnz58+fKABtIBosAyLgUGAYBQXAyLANEgG0bSAIAG0gGiwDIuBQYB
gFBcDIsA0SAbRosAQANpANFgGRcCgwDAKC4GRYBokA2jIuAgAbSAaLAMi4FBgGAUFwMiwDRIBtFB
gGAUFwMiwDRIBtHx/uR92A35hWR8Ybe4C1nwP3iv289fQK/cFfMK5A756RW38RWX1Cs5n1ivvu9g
rTQK+0V9oeUyuJ5DP7hXMK+7Zm/QV9+n/gr/SgrqFegV2ms2x8BXvCtTpFecV8H6ivUDlCkddPyF
ab1RXylIBfSbSA+04woesPGWH4B2w7qRaHxTMnVfPgfADoD0x9JXykIdyAJK+RPYhEAir9ZAVOLA
9kewiC49JzmSz/DEMYDQIARVpTrrdVX0fSnurv/rXFWK0rW6rlVf8X0qp1Stf4/Vld0ZPqARVggx
RRV/qBCQQAirEwnyDTxBlNwm1z475/qHd87GP5yFsBHXJJtOyPugvvtLacBHzDqhyzxktPVU3ckX
WXdiLShrKEF9gXEhRvJPvDF2HCR1Rc5qKOYjEDNrQ0LycBm9SsOARyUKiIq5QFVZ0bU+gJElqiir
EwV4+EPXZoE3y7hLweITnBkSA1BgIoqwLeHZLjeamkOycJuE5AuLjScKmiECHZ1wRVoiCq3NpMkW
avnEYQTLoYYfCEkiQQQkI4m4xLSq9Y2FBaGALdABtomtsA0yadJj2eC/iMTOBCEXMhM/uMpUTYZj
NjmMoqKtoQED1C8votSBUAJEkStEQVWgXFhg6ENYSSgRnJyNLQ7JBBDBBm1cYiirab+4GuaAyhwC
YKMloNhr3ATAfscjypBBoE0sIwWLACKsJBee2URVagwOnKGs2CSSRJAKq5JE6hoLbDJigAAFePLl
eGpYo5AyiWavpiZjPmLrCO5RNjmNhBcBQKg6ah8XgMBM0ACAcUgWFBNkCUkNXFKV2uWUQVWzlNZq
daDpwyBQzmXZqpU1ByZDiEFVqDtoZjmCpo27ixOuXSAqu+QnysJg5AEVe0iireFd4ExvOE3rEbr/
cAirBR8JWQEVYziRJUhqqH/xdyRThQkKWFVUkA==

------=_NextPart_000_0053_01C1ED72.B55A6760--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019