about summary refs log tree commit diff
path: root/REORG.TODO/elf
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/elf')
-rw-r--r--REORG.TODO/elf/Makefile1412
-rw-r--r--REORG.TODO/elf/Versions77
-rw-r--r--REORG.TODO/elf/cache.c829
-rw-r--r--REORG.TODO/elf/chroot_canon.c177
-rw-r--r--REORG.TODO/elf/circleload1.c166
-rw-r--r--REORG.TODO/elf/circlemod1.c7
-rw-r--r--REORG.TODO/elf/circlemod1a.c1
-rw-r--r--REORG.TODO/elf/circlemod2.c9
-rw-r--r--REORG.TODO/elf/circlemod2a.c7
-rw-r--r--REORG.TODO/elf/circlemod3.c14
-rw-r--r--REORG.TODO/elf/circlemod3a.c1
-rw-r--r--REORG.TODO/elf/constload1.c32
-rw-r--r--REORG.TODO/elf/constload2.c50
-rw-r--r--REORG.TODO/elf/constload3.c8
-rw-r--r--REORG.TODO/elf/dblload.c53
-rw-r--r--REORG.TODO/elf/dblloadmod1.c8
-rw-r--r--REORG.TODO/elf/dblloadmod2.c15
-rw-r--r--REORG.TODO/elf/dblloadmod3.c8
-rw-r--r--REORG.TODO/elf/dblunload.c53
-rw-r--r--REORG.TODO/elf/dep1.c25
-rw-r--r--REORG.TODO/elf/dep2.c25
-rw-r--r--REORG.TODO/elf/dep3.c23
-rw-r--r--REORG.TODO/elf/dep4.c24
-rw-r--r--REORG.TODO/elf/dl-addr-obj.c75
-rw-r--r--REORG.TODO/elf/dl-addr.c146
-rw-r--r--REORG.TODO/elf/dl-brk.c5
-rw-r--r--REORG.TODO/elf/dl-cache.c325
-rw-r--r--REORG.TODO/elf/dl-caller.c86
-rw-r--r--REORG.TODO/elf/dl-close.c843
-rw-r--r--REORG.TODO/elf/dl-conflict.c74
-rw-r--r--REORG.TODO/elf/dl-debug.c76
-rw-r--r--REORG.TODO/elf/dl-deps.c688
-rw-r--r--REORG.TODO/elf/dl-dst.h74
-rw-r--r--REORG.TODO/elf/dl-environ.c85
-rw-r--r--REORG.TODO/elf/dl-error-minimal.c23
-rw-r--r--REORG.TODO/elf/dl-error-skeleton.c230
-rw-r--r--REORG.TODO/elf/dl-error.c27
-rw-r--r--REORG.TODO/elf/dl-execstack.c31
-rw-r--r--REORG.TODO/elf/dl-fini.c281
-rw-r--r--REORG.TODO/elf/dl-fptr.c322
-rw-r--r--REORG.TODO/elf/dl-hwcaps.c297
-rw-r--r--REORG.TODO/elf/dl-hwcaps.h30
-rw-r--r--REORG.TODO/elf/dl-init.c126
-rw-r--r--REORG.TODO/elf/dl-iteratephdr.c89
-rw-r--r--REORG.TODO/elf/dl-libc.c330
-rw-r--r--REORG.TODO/elf/dl-load.c2307
-rw-r--r--REORG.TODO/elf/dl-load.h135
-rw-r--r--REORG.TODO/elf/dl-lookup.c1129
-rw-r--r--REORG.TODO/elf/dl-machine-reject-phdr.h34
-rw-r--r--REORG.TODO/elf/dl-map-segments.h157
-rw-r--r--REORG.TODO/elf/dl-minimal.c380
-rw-r--r--REORG.TODO/elf/dl-misc.c362
-rw-r--r--REORG.TODO/elf/dl-object.c229
-rw-r--r--REORG.TODO/elf/dl-open.c737
-rw-r--r--REORG.TODO/elf/dl-origin.c50
-rw-r--r--REORG.TODO/elf/dl-profile.c596
-rw-r--r--REORG.TODO/elf/dl-profstub.c41
-rw-r--r--REORG.TODO/elf/dl-reloc.c363
-rw-r--r--REORG.TODO/elf/dl-runtime.c480
-rw-r--r--REORG.TODO/elf/dl-sbrk.c5
-rw-r--r--REORG.TODO/elf/dl-scope.c57
-rw-r--r--REORG.TODO/elf/dl-support.c389
-rw-r--r--REORG.TODO/elf/dl-sym.c274
-rw-r--r--REORG.TODO/elf/dl-symaddr.c33
-rw-r--r--REORG.TODO/elf/dl-sysdep-open.h45
-rw-r--r--REORG.TODO/elf/dl-sysdep.c360
-rw-r--r--REORG.TODO/elf/dl-tls.c953
-rw-r--r--REORG.TODO/elf/dl-trampoline.c1
-rw-r--r--REORG.TODO/elf/dl-tunable-types.h62
-rw-r--r--REORG.TODO/elf/dl-tunables.c490
-rw-r--r--REORG.TODO/elf/dl-tunables.h115
-rw-r--r--REORG.TODO/elf/dl-tunables.list87
-rw-r--r--REORG.TODO/elf/dl-unmap-segments.h35
-rw-r--r--REORG.TODO/elf/dl-version.c389
-rw-r--r--REORG.TODO/elf/dl-writev.h56
-rw-r--r--REORG.TODO/elf/do-rel.h191
-rw-r--r--REORG.TODO/elf/dynamic-link.h203
-rw-r--r--REORG.TODO/elf/elf.h3761
-rw-r--r--REORG.TODO/elf/enbl-secure.c36
-rw-r--r--REORG.TODO/elf/failobj.c10
-rw-r--r--REORG.TODO/elf/filter.c19
-rw-r--r--REORG.TODO/elf/filtmod1.c7
-rw-r--r--REORG.TODO/elf/filtmod2.c7
-rw-r--r--REORG.TODO/elf/firstobj.c10
-rw-r--r--REORG.TODO/elf/gen-trusted-dirs.awk37
-rw-r--r--REORG.TODO/elf/genrtldtbl.awk29
-rw-r--r--REORG.TODO/elf/get-dynamic-info.h184
-rw-r--r--REORG.TODO/elf/global.c7
-rw-r--r--REORG.TODO/elf/globalmod1.c17
-rw-r--r--REORG.TODO/elf/ifuncdep1.c3
-rw-r--r--REORG.TODO/elf/ifuncdep1pic.c3
-rw-r--r--REORG.TODO/elf/ifuncdep2.c59
-rw-r--r--REORG.TODO/elf/ifuncdep2pic.c3
-rw-r--r--REORG.TODO/elf/ifuncdep5.c3
-rw-r--r--REORG.TODO/elf/ifuncdep5pic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1.c64
-rw-r--r--REORG.TODO/elf/ifuncmain1pic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1picstatic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1pie.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1static.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1staticpic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1staticpie.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1vis.c87
-rw-r--r--REORG.TODO/elf/ifuncmain1vispic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain1vispie.c3
-rw-r--r--REORG.TODO/elf/ifuncmain2.c14
-rw-r--r--REORG.TODO/elf/ifuncmain2pic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain2picstatic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain2static.c3
-rw-r--r--REORG.TODO/elf/ifuncmain3.c129
-rw-r--r--REORG.TODO/elf/ifuncmain4.c4
-rw-r--r--REORG.TODO/elf/ifuncmain4picstatic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain4static.c3
-rw-r--r--REORG.TODO/elf/ifuncmain5.c38
-rw-r--r--REORG.TODO/elf/ifuncmain5pic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain5picstatic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain5pie.c3
-rw-r--r--REORG.TODO/elf/ifuncmain5static.c3
-rw-r--r--REORG.TODO/elf/ifuncmain5staticpic.c3
-rw-r--r--REORG.TODO/elf/ifuncmain6pie.c65
-rw-r--r--REORG.TODO/elf/ifuncmain7.c72
-rw-r--r--REORG.TODO/elf/ifuncmain7pic.c7
-rw-r--r--REORG.TODO/elf/ifuncmain7picstatic.c7
-rw-r--r--REORG.TODO/elf/ifuncmain7pie.c7
-rw-r--r--REORG.TODO/elf/ifuncmain7static.c7
-rw-r--r--REORG.TODO/elf/ifuncmod1.c100
-rw-r--r--REORG.TODO/elf/ifuncmod3.c7
-rw-r--r--REORG.TODO/elf/ifuncmod5.c64
-rw-r--r--REORG.TODO/elf/ifuncmod6.c19
-rw-r--r--REORG.TODO/elf/initfirst.c22
-rw-r--r--REORG.TODO/elf/interp.c22
-rw-r--r--REORG.TODO/elf/lateglobal.c47
-rw-r--r--REORG.TODO/elf/ldconfig.c1418
-rw-r--r--REORG.TODO/elf/ldd.bash.in203
-rw-r--r--REORG.TODO/elf/link.h194
-rw-r--r--REORG.TODO/elf/loadfail.c42
-rw-r--r--REORG.TODO/elf/loadtest.c202
-rw-r--r--REORG.TODO/elf/ltglobmod1.c7
-rw-r--r--REORG.TODO/elf/ltglobmod2.c33
-rw-r--r--REORG.TODO/elf/multiload.c105
-rw-r--r--REORG.TODO/elf/neededobj1.c6
-rw-r--r--REORG.TODO/elf/neededobj2.c8
-rw-r--r--REORG.TODO/elf/neededobj3.c10
-rw-r--r--REORG.TODO/elf/neededobj4.c12
-rw-r--r--REORG.TODO/elf/neededobj5.c5
-rw-r--r--REORG.TODO/elf/neededobj6.c7
-rw-r--r--REORG.TODO/elf/neededtest.c125
-rw-r--r--REORG.TODO/elf/neededtest2.c118
-rw-r--r--REORG.TODO/elf/neededtest3.c129
-rw-r--r--REORG.TODO/elf/neededtest4.c158
-rw-r--r--REORG.TODO/elf/next.c43
-rw-r--r--REORG.TODO/elf/nextmod1.c30
-rw-r--r--REORG.TODO/elf/nextmod2.c10
-rw-r--r--REORG.TODO/elf/nodel2mod1.c19
-rw-r--r--REORG.TODO/elf/nodel2mod2.c7
-rw-r--r--REORG.TODO/elf/nodel2mod3.c1
-rw-r--r--REORG.TODO/elf/nodelete.c210
-rw-r--r--REORG.TODO/elf/nodelete2.c16
-rw-r--r--REORG.TODO/elf/nodelmod1.c9
-rw-r--r--REORG.TODO/elf/nodelmod2.c9
-rw-r--r--REORG.TODO/elf/nodelmod3.c8
-rw-r--r--REORG.TODO/elf/nodelmod4.c9
-rw-r--r--REORG.TODO/elf/nodlopen.c15
-rw-r--r--REORG.TODO/elf/nodlopen2.c15
-rw-r--r--REORG.TODO/elf/nodlopenmod.c1
-rw-r--r--REORG.TODO/elf/nodlopenmod2.c9
-rw-r--r--REORG.TODO/elf/noload.c81
-rw-r--r--REORG.TODO/elf/order.c25
-rw-r--r--REORG.TODO/elf/order2.c45
-rw-r--r--REORG.TODO/elf/order2mod1.c8
-rw-r--r--REORG.TODO/elf/order2mod2.c18
-rw-r--r--REORG.TODO/elf/order2mod3.c14
-rw-r--r--REORG.TODO/elf/order2mod4.c16
-rw-r--r--REORG.TODO/elf/origtest.c39
-rw-r--r--REORG.TODO/elf/pathoptobj.c8
-rw-r--r--REORG.TODO/elf/pldd-xx.c251
-rw-r--r--REORG.TODO/elf/pldd.c344
-rw-r--r--REORG.TODO/elf/preloadtest.c19
-rw-r--r--REORG.TODO/elf/readelflib.c234
-rw-r--r--REORG.TODO/elf/readlib.c212
-rw-r--r--REORG.TODO/elf/reldep.c111
-rw-r--r--REORG.TODO/elf/reldep2.c101
-rw-r--r--REORG.TODO/elf/reldep3.c101
-rw-r--r--REORG.TODO/elf/reldep4.c40
-rw-r--r--REORG.TODO/elf/reldep4mod1.c7
-rw-r--r--REORG.TODO/elf/reldep4mod2.c8
-rw-r--r--REORG.TODO/elf/reldep4mod3.c7
-rw-r--r--REORG.TODO/elf/reldep4mod4.c8
-rw-r--r--REORG.TODO/elf/reldep5.c70
-rw-r--r--REORG.TODO/elf/reldep6.c109
-rw-r--r--REORG.TODO/elf/reldep6mod0.c8
-rw-r--r--REORG.TODO/elf/reldep6mod1.c14
-rw-r--r--REORG.TODO/elf/reldep6mod2.c3
-rw-r--r--REORG.TODO/elf/reldep6mod3.c3
-rw-r--r--REORG.TODO/elf/reldep6mod4.c12
-rw-r--r--REORG.TODO/elf/reldep7.c58
-rw-r--r--REORG.TODO/elf/reldep7mod1.c12
-rw-r--r--REORG.TODO/elf/reldep7mod2.c12
-rw-r--r--REORG.TODO/elf/reldep8.c16
-rw-r--r--REORG.TODO/elf/reldep8mod1.c19
-rw-r--r--REORG.TODO/elf/reldep8mod2.c7
-rw-r--r--REORG.TODO/elf/reldep8mod3.c1
-rw-r--r--REORG.TODO/elf/reldep9.c16
-rw-r--r--REORG.TODO/elf/reldep9mod1.c23
-rw-r--r--REORG.TODO/elf/reldep9mod2.c3
-rw-r--r--REORG.TODO/elf/reldep9mod3.c1
-rw-r--r--REORG.TODO/elf/reldepmod1.c10
-rw-r--r--REORG.TODO/elf/reldepmod2.c8
-rw-r--r--REORG.TODO/elf/reldepmod3.c20
-rw-r--r--REORG.TODO/elf/reldepmod4.c37
-rw-r--r--REORG.TODO/elf/reldepmod5.c7
-rw-r--r--REORG.TODO/elf/reldepmod6.c8
-rw-r--r--REORG.TODO/elf/resolvfail.c31
-rw-r--r--REORG.TODO/elf/restest1.c57
-rw-r--r--REORG.TODO/elf/restest2.c33
-rw-r--r--REORG.TODO/elf/rtld-Rules149
-rw-r--r--REORG.TODO/elf/rtld-debugger-interface.txt122
-rw-r--r--REORG.TODO/elf/rtld.c2652
-rw-r--r--REORG.TODO/elf/setup-vdso.h121
-rw-r--r--REORG.TODO/elf/sln.c202
-rw-r--r--REORG.TODO/elf/sofini.c19
-rw-r--r--REORG.TODO/elf/soinit.c43
-rw-r--r--REORG.TODO/elf/sotruss-lib.c386
-rwxr-xr-xREORG.TODO/elf/sotruss.sh152
-rw-r--r--REORG.TODO/elf/sprof.c1436
-rw-r--r--REORG.TODO/elf/static-stubs.c46
-rw-r--r--REORG.TODO/elf/testobj.h28
-rw-r--r--REORG.TODO/elf/testobj1.c25
-rw-r--r--REORG.TODO/elf/testobj1_1.c7
-rw-r--r--REORG.TODO/elf/testobj2.c32
-rw-r--r--REORG.TODO/elf/testobj3.c26
-rw-r--r--REORG.TODO/elf/testobj4.c25
-rw-r--r--REORG.TODO/elf/testobj5.c26
-rw-r--r--REORG.TODO/elf/testobj6.c19
-rw-r--r--REORG.TODO/elf/tls-macros.h25
-rw-r--r--REORG.TODO/elf/tlsdeschtab.h164
-rw-r--r--REORG.TODO/elf/tst-_dl_addr_inside_object.c222
-rw-r--r--REORG.TODO/elf/tst-addr1.c25
-rw-r--r--REORG.TODO/elf/tst-align.c52
-rw-r--r--REORG.TODO/elf/tst-align2.c155
-rw-r--r--REORG.TODO/elf/tst-alignmod.c52
-rw-r--r--REORG.TODO/elf/tst-alignmod2.c59
-rw-r--r--REORG.TODO/elf/tst-array1-static.c1
-rw-r--r--REORG.TODO/elf/tst-array1.c103
-rw-r--r--REORG.TODO/elf/tst-array1.exp11
-rw-r--r--REORG.TODO/elf/tst-array2.c1
-rw-r--r--REORG.TODO/elf/tst-array2.exp19
-rw-r--r--REORG.TODO/elf/tst-array2dep.c71
-rw-r--r--REORG.TODO/elf/tst-array3.c1
-rw-r--r--REORG.TODO/elf/tst-array4.c18
-rw-r--r--REORG.TODO/elf/tst-array4.exp19
-rw-r--r--REORG.TODO/elf/tst-array5-static.c1
-rw-r--r--REORG.TODO/elf/tst-array5-static.exp2
-rw-r--r--REORG.TODO/elf/tst-array5.c50
-rw-r--r--REORG.TODO/elf/tst-array5.exp3
-rw-r--r--REORG.TODO/elf/tst-array5dep.c23
-rw-r--r--REORG.TODO/elf/tst-audit1.c1
-rw-r--r--REORG.TODO/elf/tst-audit11.c35
-rw-r--r--REORG.TODO/elf/tst-audit11mod1.c24
-rw-r--r--REORG.TODO/elf/tst-audit11mod2.c23
-rw-r--r--REORG.TODO/elf/tst-audit11mod2.map22
-rw-r--r--REORG.TODO/elf/tst-audit12.c48
-rw-r--r--REORG.TODO/elf/tst-audit12mod1.c24
-rw-r--r--REORG.TODO/elf/tst-audit12mod2.c23
-rw-r--r--REORG.TODO/elf/tst-audit12mod2.map22
-rw-r--r--REORG.TODO/elf/tst-audit12mod3.c23
-rw-r--r--REORG.TODO/elf/tst-audit2.c60
-rw-r--r--REORG.TODO/elf/tst-audit8.c1
-rw-r--r--REORG.TODO/elf/tst-audit9.c11
-rw-r--r--REORG.TODO/elf/tst-auditmod1.c135
-rw-r--r--REORG.TODO/elf/tst-auditmod11.c39
-rw-r--r--REORG.TODO/elf/tst-auditmod12.c43
-rw-r--r--REORG.TODO/elf/tst-auditmod9a.c15
-rw-r--r--REORG.TODO/elf/tst-auditmod9b.c6
-rw-r--r--REORG.TODO/elf/tst-auxv.c70
-rw-r--r--REORG.TODO/elf/tst-deep1.c35
-rw-r--r--REORG.TODO/elf/tst-deep1mod1.c14
-rw-r--r--REORG.TODO/elf/tst-deep1mod2.c16
-rw-r--r--REORG.TODO/elf/tst-deep1mod3.c17
-rw-r--r--REORG.TODO/elf/tst-dl-iter-static.c46
-rw-r--r--REORG.TODO/elf/tst-dlmodcount.c108
-rw-r--r--REORG.TODO/elf/tst-dlmopen1.c80
-rw-r--r--REORG.TODO/elf/tst-dlmopen1mod.c59
-rw-r--r--REORG.TODO/elf/tst-dlmopen2.c69
-rw-r--r--REORG.TODO/elf/tst-dlmopen3.c21
-rw-r--r--REORG.TODO/elf/tst-dlopen-aout.c67
-rw-r--r--REORG.TODO/elf/tst-dlopenrpath.c70
-rw-r--r--REORG.TODO/elf/tst-dlopenrpathmod.c35
-rw-r--r--REORG.TODO/elf/tst-dlsym-error.c113
-rw-r--r--REORG.TODO/elf/tst-env-setuid-tunables.c75
-rw-r--r--REORG.TODO/elf/tst-env-setuid.c296
-rw-r--r--REORG.TODO/elf/tst-execstack-mod.c30
-rw-r--r--REORG.TODO/elf/tst-execstack-needed.c34
-rw-r--r--REORG.TODO/elf/tst-execstack-prog.c33
-rw-r--r--REORG.TODO/elf/tst-execstack.c236
-rw-r--r--REORG.TODO/elf/tst-global1.c38
-rw-r--r--REORG.TODO/elf/tst-gnu2-tls1.c51
-rw-r--r--REORG.TODO/elf/tst-gnu2-tls1mod.c56
-rw-r--r--REORG.TODO/elf/tst-initorder.c7
-rw-r--r--REORG.TODO/elf/tst-initorder.exp13
-rw-r--r--REORG.TODO/elf/tst-initorder2.c20
-rw-r--r--REORG.TODO/elf/tst-initorder2.exp9
-rw-r--r--REORG.TODO/elf/tst-initordera1.c16
-rw-r--r--REORG.TODO/elf/tst-initordera2.c16
-rw-r--r--REORG.TODO/elf/tst-initordera3.c16
-rw-r--r--REORG.TODO/elf/tst-initordera4.c16
-rw-r--r--REORG.TODO/elf/tst-initorderb1.c16
-rw-r--r--REORG.TODO/elf/tst-initorderb2.c16
-rw-r--r--REORG.TODO/elf/tst-latepthread.c104
-rw-r--r--REORG.TODO/elf/tst-latepthreadmod.c33
-rw-r--r--REORG.TODO/elf/tst-ldconfig-X.sh62
-rw-r--r--REORG.TODO/elf/tst-leaks1-static.c1
-rw-r--r--REORG.TODO/elf/tst-leaks1.c27
-rw-r--r--REORG.TODO/elf/tst-linkall-static.c52
-rw-r--r--REORG.TODO/elf/tst-nodelete-dlclose-dso.c90
-rw-r--r--REORG.TODO/elf/tst-nodelete-dlclose-plugin.c40
-rw-r--r--REORG.TODO/elf/tst-nodelete-dlclose.c35
-rw-r--r--REORG.TODO/elf/tst-nodelete-opened-lib.c19
-rw-r--r--REORG.TODO/elf/tst-nodelete-opened.c68
-rw-r--r--REORG.TODO/elf/tst-nodelete-rtldmod.cc6
-rw-r--r--REORG.TODO/elf/tst-nodelete-uniquemod.cc14
-rw-r--r--REORG.TODO/elf/tst-nodelete-zmod.cc6
-rw-r--r--REORG.TODO/elf/tst-nodelete.cc50
-rw-r--r--REORG.TODO/elf/tst-nodelete2.c36
-rw-r--r--REORG.TODO/elf/tst-nodelete2mod.c7
-rw-r--r--REORG.TODO/elf/tst-noload.c72
-rw-r--r--REORG.TODO/elf/tst-null-argv-lib.c24
-rw-r--r--REORG.TODO/elf/tst-null-argv.c36
-rw-r--r--REORG.TODO/elf/tst-order-a1.c16
-rw-r--r--REORG.TODO/elf/tst-order-a2.c16
-rw-r--r--REORG.TODO/elf/tst-order-a3.c16
-rw-r--r--REORG.TODO/elf/tst-order-a4.c16
-rw-r--r--REORG.TODO/elf/tst-order-b1.c16
-rw-r--r--REORG.TODO/elf/tst-order-b2.c16
-rw-r--r--REORG.TODO/elf/tst-order-main.c12
-rw-r--r--REORG.TODO/elf/tst-pathopt.c41
-rwxr-xr-xREORG.TODO/elf/tst-pathopt.sh39
-rw-r--r--REORG.TODO/elf/tst-pie1.c5
-rw-r--r--REORG.TODO/elf/tst-pie2.c40
-rw-r--r--REORG.TODO/elf/tst-piemod1.c22
-rw-r--r--REORG.TODO/elf/tst-prelink.c29
-rw-r--r--REORG.TODO/elf/tst-prelink.exp1
-rw-r--r--REORG.TODO/elf/tst-protected1a.c234
-rw-r--r--REORG.TODO/elf/tst-protected1b.c240
-rw-r--r--REORG.TODO/elf/tst-protected1mod.h41
-rw-r--r--REORG.TODO/elf/tst-protected1moda.c92
-rw-r--r--REORG.TODO/elf/tst-protected1modb.c62
-rw-r--r--REORG.TODO/elf/tst-ptrguard1-static.c1
-rw-r--r--REORG.TODO/elf/tst-ptrguard1.c217
-rw-r--r--REORG.TODO/elf/tst-relsort1.c18
-rw-r--r--REORG.TODO/elf/tst-relsort1mod1.c7
-rw-r--r--REORG.TODO/elf/tst-relsort1mod2.c7
-rwxr-xr-xREORG.TODO/elf/tst-rtld-load-self.sh49
-rw-r--r--REORG.TODO/elf/tst-stackguard1-static.c1
-rw-r--r--REORG.TODO/elf/tst-stackguard1.c205
-rw-r--r--REORG.TODO/elf/tst-thrlock.c58
-rw-r--r--REORG.TODO/elf/tst-tls-dlinfo.c85
-rw-r--r--REORG.TODO/elf/tst-tls-manydynamic.c151
-rw-r--r--REORG.TODO/elf/tst-tls-manydynamic.h44
-rw-r--r--REORG.TODO/elf/tst-tls-manydynamicmod.c36
-rw-r--r--REORG.TODO/elf/tst-tls1-static.c1
-rw-r--r--REORG.TODO/elf/tst-tls1.c82
-rw-r--r--REORG.TODO/elf/tst-tls10.c39
-rw-r--r--REORG.TODO/elf/tst-tls10.h32
-rw-r--r--REORG.TODO/elf/tst-tls11.c28
-rw-r--r--REORG.TODO/elf/tst-tls12.c19
-rw-r--r--REORG.TODO/elf/tst-tls13.c28
-rw-r--r--REORG.TODO/elf/tst-tls14.c54
-rw-r--r--REORG.TODO/elf/tst-tls15.c32
-rw-r--r--REORG.TODO/elf/tst-tls16.c52
-rw-r--r--REORG.TODO/elf/tst-tls17.c28
-rw-r--r--REORG.TODO/elf/tst-tls18.c37
-rw-r--r--REORG.TODO/elf/tst-tls19.c26
-rw-r--r--REORG.TODO/elf/tst-tls19mod1.c15
-rw-r--r--REORG.TODO/elf/tst-tls19mod2.c13
-rw-r--r--REORG.TODO/elf/tst-tls19mod3.c16
-rw-r--r--REORG.TODO/elf/tst-tls2-static.c1
-rw-r--r--REORG.TODO/elf/tst-tls2.c82
-rw-r--r--REORG.TODO/elf/tst-tls3.c67
-rw-r--r--REORG.TODO/elf/tst-tls4.c49
-rw-r--r--REORG.TODO/elf/tst-tls5.c65
-rw-r--r--REORG.TODO/elf/tst-tls6.c84
-rw-r--r--REORG.TODO/elf/tst-tls7.c55
-rw-r--r--REORG.TODO/elf/tst-tls8.c167
-rw-r--r--REORG.TODO/elf/tst-tls9-static.c1
-rw-r--r--REORG.TODO/elf/tst-tls9.c36
-rw-r--r--REORG.TODO/elf/tst-tlsalign-extern-static.c1
-rw-r--r--REORG.TODO/elf/tst-tlsalign-extern.c73
-rw-r--r--REORG.TODO/elf/tst-tlsalign-lib.c6
-rw-r--r--REORG.TODO/elf/tst-tlsalign-static.c2
-rw-r--r--REORG.TODO/elf/tst-tlsalign-vars.c28
-rw-r--r--REORG.TODO/elf/tst-tlsalign.c84
-rw-r--r--REORG.TODO/elf/tst-tlsmod1.c62
-rw-r--r--REORG.TODO/elf/tst-tlsmod10.c1
-rw-r--r--REORG.TODO/elf/tst-tlsmod11.c4
-rw-r--r--REORG.TODO/elf/tst-tlsmod12.c12
-rw-r--r--REORG.TODO/elf/tst-tlsmod13.c7
-rw-r--r--REORG.TODO/elf/tst-tlsmod13a.c9
-rw-r--r--REORG.TODO/elf/tst-tlsmod14a.c35
-rw-r--r--REORG.TODO/elf/tst-tlsmod14b.c2
-rw-r--r--REORG.TODO/elf/tst-tlsmod15a.c6
-rw-r--r--REORG.TODO/elf/tst-tlsmod15b.c9
-rw-r--r--REORG.TODO/elf/tst-tlsmod16a.c1
-rw-r--r--REORG.TODO/elf/tst-tlsmod16b.c7
-rw-r--r--REORG.TODO/elf/tst-tlsmod17a.c23
-rw-r--r--REORG.TODO/elf/tst-tlsmod17b.c15
-rw-r--r--REORG.TODO/elf/tst-tlsmod18a.c21
-rw-r--r--REORG.TODO/elf/tst-tlsmod2.c34
-rw-r--r--REORG.TODO/elf/tst-tlsmod3.c37
-rw-r--r--REORG.TODO/elf/tst-tlsmod4.c34
-rw-r--r--REORG.TODO/elf/tst-tlsmod5.c3
-rw-r--r--REORG.TODO/elf/tst-tlsmod6.c3
-rw-r--r--REORG.TODO/elf/tst-tlsmod7.c101
-rw-r--r--REORG.TODO/elf/tst-tlsmod8.c70
-rw-r--r--REORG.TODO/elf/tst-tlsmod9.c99
-rw-r--r--REORG.TODO/elf/tst-unique1.c73
-rw-r--r--REORG.TODO/elf/tst-unique1mod1.c16
-rw-r--r--REORG.TODO/elf/tst-unique1mod2.c15
-rw-r--r--REORG.TODO/elf/tst-unique2.c27
-rw-r--r--REORG.TODO/elf/tst-unique2mod1.c8
-rw-r--r--REORG.TODO/elf/tst-unique2mod2.c15
-rw-r--r--REORG.TODO/elf/tst-unique3.cc24
-rw-r--r--REORG.TODO/elf/tst-unique3.h8
-rw-r--r--REORG.TODO/elf/tst-unique3lib.cc11
-rw-r--r--REORG.TODO/elf/tst-unique3lib2.cc12
-rw-r--r--REORG.TODO/elf/tst-unique4.cc28
-rw-r--r--REORG.TODO/elf/tst-unique4.h7
-rw-r--r--REORG.TODO/elf/tst-unique4lib.cc17
-rw-r--r--REORG.TODO/elf/unload.c91
-rw-r--r--REORG.TODO/elf/unload2.c59
-rw-r--r--REORG.TODO/elf/unload2dep.c6
-rw-r--r--REORG.TODO/elf/unload2mod.c8
-rw-r--r--REORG.TODO/elf/unload3.c41
-rw-r--r--REORG.TODO/elf/unload3mod1.c1
-rw-r--r--REORG.TODO/elf/unload3mod2.c1
-rw-r--r--REORG.TODO/elf/unload3mod3.c8
-rw-r--r--REORG.TODO/elf/unload3mod4.c13
-rw-r--r--REORG.TODO/elf/unload4.c48
-rw-r--r--REORG.TODO/elf/unload4mod1.c10
-rw-r--r--REORG.TODO/elf/unload4mod2.c8
-rw-r--r--REORG.TODO/elf/unload4mod3.c16
-rw-r--r--REORG.TODO/elf/unload4mod4.c16
-rw-r--r--REORG.TODO/elf/unload5.c42
-rw-r--r--REORG.TODO/elf/unload6.c30
-rw-r--r--REORG.TODO/elf/unload6mod1.c16
-rw-r--r--REORG.TODO/elf/unload6mod2.c23
-rw-r--r--REORG.TODO/elf/unload6mod3.c23
-rw-r--r--REORG.TODO/elf/unload7.c39
-rw-r--r--REORG.TODO/elf/unload7mod1.c11
-rw-r--r--REORG.TODO/elf/unload7mod2.c1
-rw-r--r--REORG.TODO/elf/unload8.c33
-rw-r--r--REORG.TODO/elf/unload8mod1.c7
-rw-r--r--REORG.TODO/elf/unload8mod1x.c1
-rw-r--r--REORG.TODO/elf/unload8mod2.c7
-rw-r--r--REORG.TODO/elf/unload8mod3.c27
-rw-r--r--REORG.TODO/elf/unloadmod.c4
-rw-r--r--REORG.TODO/elf/vismain.c260
-rw-r--r--REORG.TODO/elf/vismod.h27
-rw-r--r--REORG.TODO/elf/vismod1.c103
-rw-r--r--REORG.TODO/elf/vismod2.c123
-rw-r--r--REORG.TODO/elf/vismod3.c46
461 files changed, 43439 insertions, 0 deletions
diff --git a/REORG.TODO/elf/Makefile b/REORG.TODO/elf/Makefile
new file mode 100644
index 0000000000..201b328f88
--- /dev/null
+++ b/REORG.TODO/elf/Makefile
@@ -0,0 +1,1412 @@
+# Copyright (C) 1995-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# Makefile for elf subdirectory of GNU C Library.
+
+subdir		:= elf
+
+include ../Makeconfig
+
+headers		= elf.h bits/elfclass.h link.h bits/link.h
+routines	= $(all-dl-routines) dl-support dl-iteratephdr \
+		  dl-addr dl-addr-obj enbl-secure dl-profstub \
+		  dl-origin dl-libc dl-sym dl-sysdep dl-error
+
+# The core dynamic linking functions are in libc for the static and
+# profiled libraries.
+dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
+				  runtime init fini debug misc \
+				  version profile conflict tls origin scope \
+				  execstack caller open close trampoline)
+ifeq (yes,$(use-ldconfig))
+dl-routines += dl-cache
+endif
+
+ifneq (no,$(have-tunables))
+dl-routines += dl-tunables
+tunables-type = $(addprefix TUNABLES_FRONTEND_,$(have-tunables))
+CPPFLAGS-dl-tunables.c = -DTUNABLES_FRONTEND=$(tunables-type)
+
+# Make sure that the compiler does not insert any library calls in tunables
+# code paths.
+ifeq (yes,$(have-loop-to-function))
+CFLAGS-dl-tunables.c = -fno-tree-loop-distribute-patterns
+endif
+endif
+
+all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
+# But they are absent from the shared libc, because that code is in ld.so.
+elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
+		    dl-sysdep
+shared-only-routines += dl-caller
+
+# ld.so uses those routines, plus some special stuff for being the program
+# interpreter and operating independent of libc.
+rtld-routines	= rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \
+  dl-error-minimal
+all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
+
+CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-dl-iterate-phdr.c = $(uses-callbacks)
+
+# Compile rtld itself without stack protection.
+# Also compile all routines in the static library that are elided from
+# the shared libc because they are in libc.a in the same way.
+
+define elide-stack-protector
+$(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-stack-protector))
+endef
+
+CFLAGS-.o += $(call elide-stack-protector,.o,$(elide-routines.os))
+CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os))
+CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
+
+ifeq ($(unwind-find-fde),yes)
+routines += unwind-dw2-fde-glibc
+shared-only-routines += unwind-dw2-fde-glibc
+endif
+
+before-compile  += $(objpfx)trusted-dirs.h
+generated	+= trusted-dirs.h trusted-dirs.st for-renamed/renamed.so
+generated-dirs	+= for-renamed
+
+ifeq ($(build-shared),yes)
+ld-map		= $(common-objpfx)ld.map
+endif
+
+ifeq (yes,$(build-shared))
+extra-objs	= $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os
+generated	+= librtld.os dl-allobjs.os ld.so ldd
+install-others	= $(inst_rtlddir)/$(rtld-installed-name)
+install-bin-script = ldd
+endif
+
+others		= sprof sln
+install-bin	= sprof
+others-static   = sln
+install-rootsbin = sln
+sln-modules	:= static-stubs
+extra-objs	+= $(sln-modules:=.o)
+
+ifeq (yes,$(use-ldconfig))
+ifeq (yes,$(build-shared))
+others-static	+= ldconfig
+others		+= ldconfig
+install-rootsbin += ldconfig
+
+ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs
+extra-objs	+= $(ldconfig-modules:=.o)
+endif
+endif
+
+# To find xmalloc.c and xstrdup.c
+vpath %.c ../locale/programs
+
+ifeq ($(build-shared),yes)
+extra-objs += sotruss-lib.os sotruss-lib.so
+install-others += $(inst_auditdir)/sotruss-lib.so
+install-bin-script += sotruss
+generated += sotruss
+libof-sotruss-lib = extramodules
+$(objpfx)sotruss-lib.so: $(objpfx)sotruss-lib.os
+	$(build-module-asneeded)
+$(objpfx)sotruss-lib.so: $(common-objpfx)libc.so $(objpfx)ld.so \
+	$(common-objpfx)libc_nonshared.a
+
+$(objpfx)sotruss: sotruss.sh $(common-objpfx)config.make
+	sed -e 's%@BASH@%$(BASH)%g' \
+	    -e 's%@VERSION@%$(version)%g' \
+	    -e 's%@TEXTDOMAINDIR@%$(localedir)%g' \
+	    -e 's%@PREFIX@%$(prefix)%g' \
+	    -e 's|@PKGVERSION@|$(PKGVERSION)|g' \
+	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|g' \
+	    < $< > $@.new
+	chmod 555 $@.new
+	mv -f $@.new $@
+$(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)
+	$(do-install-program)
+endif
+
+tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
+	       tst-dl-iter-static \
+	       tst-tlsalign-static tst-tlsalign-extern-static \
+	       tst-linkall-static tst-env-setuid tst-env-setuid-tunables
+tests-static-internal := tst-tls1-static tst-tls2-static \
+	       tst-ptrguard1-static tst-stackguard1-static
+
+tests := tst-tls9 tst-leaks1 \
+	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
+	tst-auxv
+tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
+tests-static := $(tests-static-normal) $(tests-static-internal)
+
+ifeq (yes,$(build-shared))
+tests-static += tst-tls9-static
+tst-tls9-static-ENV = \
+       LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+
+tests += restest1 preloadtest loadfail multiload origtest resolvfail \
+	 constload1 order noload filter \
+	 reldep reldep2 reldep3 reldep4 nodelete nodelete2 \
+	 nodlopen nodlopen2 lateglobal initfirst global \
+	 restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
+	 tst-tls4 tst-tls5 \
+	 tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
+	 tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
+	 tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
+	 tst-dlmodcount tst-dlopenrpath tst-deep1 \
+	 tst-dlmopen1 tst-dlmopen3 \
+	 unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
+	 tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
+	 tst-addr1 tst-thrlock \
+	 tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
+	 tst-nodelete) \
+	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+	 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
+	 tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
+	 tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose
+#	 reldep9
+tests-internal += loadtest unload unload2 circleload1 \
+	 neededtest neededtest2 neededtest3 neededtest4 \
+	 tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
+	 tst-ptrguard1 tst-stackguard1
+ifeq ($(build-hardcoded-path-in-tests),yes)
+tests += tst-dlopen-aout
+LDFLAGS-tst-dlopen-aout = $(no-pie-ldflag)
+endif
+test-srcs = tst-pathopt
+selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
+ifneq ($(selinux-enabled),1)
+tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
+endif
+endif
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-leaks1-mem.out \
+		 $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
+		 $(objpfx)tst-ldconfig-X.out
+endif
+tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+tlsmod17a-modules = $(addprefix tst-tlsmod17a, $(tlsmod17a-suffixes))
+tlsmod18a-modules = $(addprefix tst-tlsmod18a, $(tlsmod17a-suffixes))
+one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
+  0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x)
+tst-tls-many-dynamic-modules := \
+  $(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod)
+extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \
+		   tst-tlsalign-vars.o
+test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars
+modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+		testobj1_1 failobj constload2 constload3 unloadmod \
+		dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \
+		nodelmod1 nodelmod2 nodelmod3 nodelmod4 \
+		nodel2mod1 nodel2mod2 nodel2mod3 \
+		nodlopenmod nodlopenmod2 filtmod1 filtmod2 \
+		reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
+		reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \
+		neededobj1 neededobj2 neededobj3 neededobj4 \
+		neededobj5 neededobj6 firstobj globalmod1 \
+		unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \
+		dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \
+		reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \
+		reldep7mod1 reldep7mod2 \
+		tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \
+		tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
+		tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
+		tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
+		tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \
+		$(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \
+		tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
+		circlemod1 circlemod1a circlemod2 circlemod2a \
+		circlemod3 circlemod3a \
+		reldep8mod1 reldep8mod2 reldep8mod3 \
+		reldep9mod1 reldep9mod2 reldep9mod3 \
+		tst-alignmod tst-alignmod2 \
+		$(modules-execstack-$(have-z-execstack)) \
+		tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
+		tst-dlmopen1mod tst-auditmod1 \
+		unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
+		unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
+		unload6mod1 unload6mod2 unload6mod3 \
+		unload7mod1 unload7mod2 \
+		unload8mod1 unload8mod1x unload8mod2 unload8mod3 \
+		order2mod1 order2mod2 order2mod3 order2mod4 \
+		tst-unique1mod1 tst-unique1mod2 \
+		tst-unique2mod1 tst-unique2mod2 \
+		tst-auditmod9a tst-auditmod9b \
+		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
+		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
+		  tst-nodelete-zmod) \
+		tst-initordera1 tst-initorderb1 \
+		tst-initordera2 tst-initorderb2 \
+		tst-initordera3 tst-initordera4 \
+		tst-initorder2a tst-initorder2b tst-initorder2c \
+		tst-initorder2d \
+		tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
+		tst-array5dep tst-null-argv-lib \
+		tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
+		tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
+		tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
+		tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
+		tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin
+ifeq (yes,$(have-mtls-dialect-gnu2))
+tests += tst-gnu2-tls1
+modules-names += tst-gnu2-tls1mod
+$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
+tst-gnu2-tls1mod.so-no-z-defs = yes
+CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
+endif
+ifeq (yes,$(have-protected-data))
+modules-names += tst-protected1moda tst-protected1modb
+tests += tst-protected1a tst-protected1b
+$(objpfx)tst-protected1a: $(addprefix $(objpfx),tst-protected1moda.so tst-protected1modb.so)
+$(objpfx)tst-protected1b: $(addprefix $(objpfx),tst-protected1modb.so tst-protected1moda.so)
+tst-protected1modb.so-no-z-defs = yes
+# These tests fail with GCC versions prior to 5.1 and with some versions
+# of binutils.  See https://sourceware.org/bugzilla/show_bug.cgi?id=17709
+# and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248 for details.
+# Perhaps in future we can make these XFAILs conditional on some detection
+# of compiler/linker behavior/version.
+test-xfail-tst-protected1a = yes
+test-xfail-tst-protected1b = yes
+endif
+ifeq (yesyes,$(have-fpie)$(build-shared))
+modules-names += tst-piemod1
+tests += tst-pie1 tst-pie2
+tests-pie += tst-pie1 tst-pie2
+tests += vismain
+tests-pie += vismain
+CFLAGS-vismain.c = $(PIE-ccflag)
+endif
+modules-execstack-yes = tst-execstack-mod
+extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
+
+# filtmod1.so has a special rule
+modules-names-nobuild := filtmod1
+
+tests += $(tests-static)
+
+ifneq (no,$(multi-arch))
+tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \
+		ifuncmain2static ifuncmain2picstatic \
+		ifuncmain4static ifuncmain4picstatic \
+		ifuncmain5static ifuncmain5picstatic \
+		ifuncmain7static ifuncmain7picstatic
+tests-static += $(tests-ifuncstatic)
+tests-internal += $(tests-ifuncstatic)
+ifeq (yes,$(build-shared))
+tests-internal += \
+	 ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \
+	 ifuncmain1staticpic \
+	 ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \
+	 ifuncmain5 ifuncmain5pic ifuncmain5staticpic \
+	 ifuncmain7 ifuncmain7pic
+ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \
+		     ifuncdep5 ifuncdep5pic
+extra-test-objs += $(ifunc-test-modules:=.o)
+test-internal-extras += $(ifunc-test-modules)
+ifeq (yes,$(have-fpie))
+ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \
+		  ifuncmain5pie ifuncmain6pie ifuncmain7pie
+tests-internal += $(ifunc-pie-tests)
+tests-pie += $(ifunc-pie-tests)
+endif
+modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6
+endif
+endif
+
+ifeq (yes,$(build-shared))
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out
+endif
+tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
+		 $(objpfx)check-localplt.out
+endif
+
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \
+		 $(objpfx)tst-array1-static-cmp.out \
+		 $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \
+		 $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \
+		 $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \
+		 $(objpfx)tst-initorder-cmp.out \
+		 $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \
+		 $(objpfx)tst-unused-dep-cmp.out
+endif
+
+check-abi: $(objpfx)check-abi-ld.out
+tests-special += $(objpfx)check-abi-ld.out
+update-abi: update-abi-ld
+update-all-abi: update-all-abi-ld
+
+ifeq ($(have-glob-dat-reloc),yes)
+tests += tst-prelink
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-prelink-cmp.out
+endif
+endif
+
+# The test requires shared _and_ PIE because the executable
+# unit test driver must be able to link with the shared object
+# that is going to eventually go into an installed DSO.
+ifeq (yesyes,$(have-fpie)$(build-shared))
+tests-internal += tst-_dl_addr_inside_object
+tests-pie += tst-_dl_addr_inside_object
+$(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os
+CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
+endif
+
+# By default tst-linkall-static should try to use crypt routines to test
+# static libcrypt use.
+CFLAGS-tst-linkall-static.c = -DUSE_CRYPT=1
+# However, if we are using NSS crypto and we don't have a static
+# library, then we exclude the use of crypt functions in the test.
+# We similarly exclude libcrypt.a from the static link (see below).
+ifeq (yesno,$(nss-crypt)$(static-nss-crypt))
+CFLAGS-tst-linkall-static.c = -DUSE_CRYPT=0
+endif
+
+include ../Rules
+
+ifeq (yes,$(build-shared))
+# Make sure these things are built in the `make lib' pass so they can be used
+# to run programs during the `make others' pass.
+lib-noranlib: $(objpfx)$(rtld-installed-name) \
+	      $(addprefix $(objpfx),$(extra-objs))
+endif
+
+# Command to link into a larger single relocatable object.
+reloc-link = $(LINK.o) -nostdlib -nostartfiles -r
+
+$(objpfx)sotruss-lib.so: $(shlib-lds)
+
+$(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
+	$(reloc-link) -o $@ $^
+
+# Link together the dynamic linker into a single relocatable object.
+# First we do a link against libc_pic.a just to get a link map,
+# and discard the object produced by that link.  From the link map
+# we can glean all the libc modules that need to go into the dynamic
+# linker.  Then we do a recursive make that goes into all the subdirs
+# those modules come from and builds special rtld-foo.os versions that
+# are compiled with special flags, and puts these modules into rtld-libc.a
+# for us.  Then we do the real link using rtld-libc.a instead of libc_pic.a.
+
+# If the compiler can do SSP, build the mapfile with dummy __stack_chk_fail
+# and __stack_chk_fail_local symbols defined, to prevent the real things
+# being dragged into rtld even though rtld is never built with stack-
+# protection.
+
+ifeq ($(have-ssp),yes)
+dummy-stack-chk-fail := -Wl,--defsym='__stack_chk_fail=0' \
+			-Wl,--defsym='__stack_chk_fail_local=0'
+else
+dummy-stack-chk-fail :=
+endif
+
+$(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
+	@-rm -f $@T
+	$(reloc-link) -o $@.o $(dummy-stack-chk-fail) \
+		'-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@T
+	rm -f $@.o
+	mv -f $@T $@
+
+$(objpfx)librtld.mk: $(objpfx)librtld.map Makefile
+	LC_ALL=C \
+	sed -n 's@^$(common-objpfx)\([^(]*\)(\([^)]*\.os\)) *.*$$@\1 \2@p' \
+	    $< | \
+	while read lib file; do \
+	  case $$lib in \
+	  libc_pic.a) \
+	    LC_ALL=C fgrep -l /$$file \
+		  $(common-objpfx)stamp.os $(common-objpfx)*/stamp.os | \
+	    LC_ALL=C \
+	    sed 's@^$(common-objpfx)\([^/]*\)/stamp\.os$$@rtld-\1'" +=$$file@"\
+	    ;; \
+	  */*.a) \
+	    echo rtld-$${lib%%/*} += $$file ;; \
+	  *) echo "Wasn't expecting $$lib($$file)" >&2; exit 1 ;; \
+	  esac; \
+	done > $@T
+	echo rtld-subdirs = `LC_ALL=C sed 's/^rtld-\([^ ]*\).*$$/\1/' $@T \
+			     | LC_ALL=C sort -u` >> $@T
+	mv -f $@T $@
+
+$(objpfx)rtld-libc.a: $(objpfx)librtld.mk FORCE
+	$(MAKE) -f $< -f rtld-Rules
+
+$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(objpfx)rtld-libc.a
+	$(LINK.o) -nostdlib -nostartfiles -r -o $@ '-Wl,-(' $^ -lgcc '-Wl,-)' \
+		  -Wl,-Map,$@.map
+
+generated += librtld.map librtld.mk rtld-libc.a librtld.os.map
+
+z-now-yes = -Wl,-z,now
+
+$(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
+# Link into a temporary file so that we don't touch $@ at all
+# if the sanity check below fails.
+	$(LINK.o) -nostdlib -nostartfiles -shared -o $@.new		\
+		  $(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now))	\
+		  $(filter-out $(map-file),$^) $(load-map-file)		\
+		  -Wl,-soname=$(rtld-installed-name)			\
+		  -Wl,-defsym=_begin=0
+	$(call after-link,$@.new)
+	$(READELF) -s $@.new \
+	  | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }'
+	mv -f $@.new $@
+
+ifeq (yes,$(build-shared))
+# interp.c exists just to get the runtime linker path into libc.so.
+$(objpfx)interp.os: $(common-objpfx)runtime-linker.h
+endif
+
+ifneq (ld.so,$(rtld-installed-name))
+# Make sure ld.so.1 exists in the build directory so we can link
+# against it.
+$(objpfx)$(rtld-installed-name): $(objpfx)ld.so
+	$(make-link)
+generated += $(rtld-installed-name)
+endif
+
+# Build a file mentioning all trustworthy directories to look for shared
+# libraries when using LD_LIBRARY_PATH in a setuid program.  The user can
+# add directories to the list by defining $(user-defined-trusted-dirs)
+# before starting make.
+$(objpfx)trusted-dirs.h: $(objpfx)trusted-dirs.st; @:
+$(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig
+	$(make-target-directory)
+	echo "$(subst :, ,$(default-rpath) $(user-defined-trusted-dirs))"    \
+	| $(AWK) -f gen-trusted-dirs.awk > ${@:st=T};
+	echo '#define DL_DST_LIB "$(notdir $(slibdir))"' >> ${@:st=T}
+	$(move-if-change) ${@:st=T} ${@:st=h}
+	touch $@
+CPPFLAGS-dl-load.c = -I$(objpfx). -I$(csu-objpfx).
+
+ifeq (yes,$(build-shared))
+$(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force)
+	$(make-target-directory)
+	$(do-install-program)
+
+$(inst_rtlddir)/$(rtld-installed-name): \
+  $(inst_slibdir)/$(rtld-version-installed-name) \
+  $(inst_slibdir)/libc-$(version).so
+	$(make-target-directory)
+	$(make-shlib-link)
+
+# Special target called by parent to install just the dynamic linker.
+.PHONY: ldso_install
+ldso_install: $(inst_rtlddir)/$(rtld-installed-name)
+endif
+
+
+ldd-rewrite = -e 's%@RTLD@%$(rtlddir)/$(rtld-installed-name)%g' \
+	      -e 's%@VERSION@%$(version)%g' \
+	      -e 's|@PKGVERSION@|$(PKGVERSION)|g' \
+	      -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|g' \
+	      -e 's%@BASH@%$(BASH)%g' \
+	      -e 's%@TEXTDOMAINDIR@%$(localedir)%g'
+
+ifeq ($(ldd-rewrite-script),no)
+define gen-ldd
+LC_ALL=C sed $(ldd-rewrite) < $< > $@.new
+endef
+else
+define gen-ldd
+LC_ALL=C sed $(ldd-rewrite) < $< \
+| LC_ALL=C sed -f $(patsubst $(..)/%,/%,$(..)$(ldd-rewrite-script)) > $@.new
+endef
+endif
+
+$(objpfx)ldd: ldd.bash.in $(common-objpfx)soversions.mk \
+	      $(common-objpfx)config.make
+	$(gen-ldd)
+	chmod 555 $@.new
+	mv -f $@.new $@
+
+$(objpfx)sprof: $(libdl)
+
+$(objpfx)sln: $(sln-modules:%=$(objpfx)%.o)
+
+$(objpfx)ldconfig: $(ldconfig-modules:%=$(objpfx)%.o)
+
+SYSCONF-FLAGS := -D'SYSCONFDIR="$(sysconfdir)"'
+CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \
+		    -D'SLIBDIR="$(slibdir)"'
+libof-ldconfig = ldconfig
+CFLAGS-dl-cache.c = $(SYSCONF-FLAGS)
+CFLAGS-cache.c = $(SYSCONF-FLAGS)
+CFLAGS-rtld.c = $(SYSCONF-FLAGS)
+
+cpp-srcs-left := $(all-rtld-routines:=.os)
+lib := rtld
+include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
+
+test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names))))
+generated += $(addsuffix .so,$(strip $(modules-names)))
+
+$(objpfx)testobj1.so: $(libdl)
+$(objpfx)testobj1_1.so: $(objpfx)testobj1.so $(libdl)
+$(objpfx)testobj2.so: $(objpfx)testobj1.so $(libdl)
+$(objpfx)testobj3.so: $(libdl)
+$(objpfx)testobj4.so: $(libdl)
+$(objpfx)testobj5.so: $(libdl)
+$(objpfx)testobj6.so: $(objpfx)testobj1.so $(objpfx)testobj2.so $(libdl)
+$(objpfx)failobj.so: $(objpfx)testobj6.so
+$(objpfx)dep1.so: $(objpfx)dep2.so $(objpfx)dep4.so
+$(objpfx)dep2.so: $(objpfx)dep3.so $(objpfx)dep4.so
+$(objpfx)dep4.so: $(objpfx)dep3.so
+$(objpfx)nodelmod3.so: $(objpfx)nodelmod4.so
+$(objpfx)nextmod1.so: $(libdl)
+$(objpfx)neededobj1.so: $(libdl)
+$(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl)
+$(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl)
+$(objpfx)neededobj4.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
+			$(objpfx)neededobj3.so $(libdl)
+$(objpfx)neededobj6.so: $(objpfx)neededobj5.so
+$(objpfx)unload2mod.so: $(objpfx)unload2dep.so
+$(objpfx)ltglobmod2.so: $(libdl)
+$(objpfx)firstobj.so: $(shared-thread-library)
+$(objpfx)globalmod1.so: $(libdl)
+$(objpfx)reldep4mod1.so: $(objpfx)reldep4mod3.so
+$(objpfx)reldep4mod2.so: $(objpfx)reldep4mod4.so
+$(objpfx)dblloadmod1.so: $(objpfx)dblloadmod3.so
+$(objpfx)dblloadmod2.so: $(objpfx)dblloadmod3.so
+$(objpfx)reldepmod5.so: $(objpfx)reldepmod2.so
+$(objpfx)reldepmod6.so: $(objpfx)reldepmod2.so
+$(objpfx)reldep6mod1.so: $(objpfx)reldep6mod0.so
+$(objpfx)reldep6mod2.so: $(objpfx)reldep6mod1.so
+$(objpfx)reldep6mod3.so: $(objpfx)reldep6mod2.so
+$(objpfx)reldep6mod4.so: $(objpfx)reldep6mod1.so
+$(objpfx)tst-tlsmod3.so: $(objpfx)tst-tlsmod2.so
+$(objpfx)tst-tlsmod8.so: $(objpfx)tst-tlsmod7.so
+$(objpfx)tst-tlsmod10.so: $(objpfx)tst-tlsmod9.so
+$(objpfx)tst-tlsmod12.so: $(objpfx)tst-tlsmod11.so
+$(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so
+# For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED
+$(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so
+$(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so
+$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so
+$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so
+$(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so
+$(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so
+$(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so
+$(objpfx)reldep9mod3.so: $(objpfx)reldep9mod1.so $(objpfx)reldep9mod2.so
+$(objpfx)unload3mod1.so: $(objpfx)unload3mod3.so
+$(objpfx)unload3mod2.so: $(objpfx)unload3mod3.so
+$(objpfx)unload3mod3.so: $(objpfx)unload3mod4.so
+$(objpfx)unload4mod1.so: $(objpfx)unload4mod2.so $(objpfx)unload4mod3.so
+$(objpfx)unload4mod2.so: $(objpfx)unload4mod4.so $(objpfx)unload4mod3.so
+$(objpfx)unload6mod1.so: $(libdl)
+$(objpfx)unload6mod2.so: $(libdl)
+$(objpfx)unload6mod3.so: $(libdl)
+$(objpfx)unload7mod1.so: $(libdl)
+$(objpfx)unload7mod2.so: $(objpfx)unload7mod1.so
+$(objpfx)unload8mod1.so: $(objpfx)unload8mod2.so
+$(objpfx)unload8mod2.so: $(objpfx)unload8mod3.so
+$(objpfx)unload8mod3.so: $(libdl)
+$(objpfx)tst-initordera2.so: $(objpfx)tst-initordera1.so
+$(objpfx)tst-initorderb2.so: $(objpfx)tst-initorderb1.so $(objpfx)tst-initordera2.so
+$(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb1.so
+$(objpfx)tst-initordera4.so: $(objpfx)tst-initordera3.so
+$(objpfx)tst-initorder: $(objpfx)tst-initordera4.so $(objpfx)tst-initordera1.so $(objpfx)tst-initorderb2.so
+$(objpfx)tst-null-argv: $(objpfx)tst-null-argv-lib.so
+$(objpfx)tst-tlsalign: $(objpfx)tst-tlsalign-lib.so
+$(objpfx)tst-nodelete-opened.out: $(objpfx)tst-nodelete-opened-lib.so
+$(objpfx)tst-nodelete-opened: $(libdl)
+$(objpfx)tst-noload: $(libdl)
+
+$(objpfx)tst-tlsalign-extern: $(objpfx)tst-tlsalign-vars.o
+$(objpfx)tst-tlsalign-extern-static: $(objpfx)tst-tlsalign-vars.o
+
+tst-null-argv-ENV = LD_DEBUG=all LD_DEBUG_OUTPUT=$(objpfx)tst-null-argv.debug.out
+LDFLAGS-nodel2mod3.so = $(no-as-needed)
+LDFLAGS-reldepmod5.so = $(no-as-needed)
+LDFLAGS-reldep6mod1.so = $(no-as-needed)
+LDFLAGS-reldep6mod4.so = $(no-as-needed)
+LDFLAGS-reldep8mod3.so = $(no-as-needed)
+LDFLAGS-unload4mod1.so = $(no-as-needed)
+LDFLAGS-unload4mod2.so = $(no-as-needed)
+LDFLAGS-tst-initorder = $(no-as-needed)
+LDFLAGS-tst-initordera2.so = $(no-as-needed)
+LDFLAGS-tst-initordera3.so = $(no-as-needed)
+LDFLAGS-tst-initordera4.so = $(no-as-needed)
+LDFLAGS-tst-initorderb2.so = $(no-as-needed)
+LDFLAGS-tst-tlsmod5.so = -nostdlib $(no-as-needed)
+LDFLAGS-tst-tlsmod6.so = -nostdlib $(no-as-needed)
+
+testobj1.so-no-z-defs = yes
+testobj3.so-no-z-defs = yes
+testobj4.so-no-z-defs = yes
+testobj5.so-no-z-defs = yes
+testobj6.so-no-z-defs = yes
+failobj.so-no-z-defs = yes
+constload2.so-no-z-defs = yes
+constload3.so-no-z-defs = yes
+nodelmod1.so-no-z-defs = yes
+nodelmod2.so-no-z-defs = yes
+nodelmod4.so-no-z-defs = yes
+nodel2mod2.so-no-z-defs = yes
+reldepmod2.so-no-z-defs = yes
+reldepmod3.so-no-z-defs = yes
+reldepmod4.so-no-z-defs = yes
+reldep4mod4.so-no-z-defs = yes
+reldep4mod2.so-no-z-defs = yes
+ltglobmod2.so-no-z-defs = yes
+dblloadmod3.so-no-z-defs = yes
+tst-tlsmod1.so-no-z-defs = yes
+tst-tlsmod2.so-no-z-defs = yes
+tst-tlsmod3.so-no-z-defs = yes
+tst-tlsmod4.so-no-z-defs = yes
+tst-tlsmod7.so-no-z-defs = yes
+tst-tlsmod8.so-no-z-defs = yes
+tst-tlsmod9.so-no-z-defs = yes
+tst-tlsmod10.so-no-z-defs = yes
+tst-tlsmod12.so-no-z-defs = yes
+tst-tlsmod14a.so-no-z-defs = yes
+tst-tlsmod14b.so-no-z-defs = yes
+tst-tlsmod15a.so-no-z-defs = yes
+tst-tlsmod16b.so-no-z-defs = yes
+circlemod2.so-no-z-defs = yes
+circlemod3.so-no-z-defs = yes
+circlemod3a.so-no-z-defs = yes
+reldep8mod2.so-no-z-defs = yes
+reldep9mod1.so-no-z-defs = yes
+unload3mod4.so-no-z-defs = yes
+unload4mod1.so-no-z-defs = yes
+ifuncmod1.so-no-z-defs = yes
+ifuncmod5.so-no-z-defs = yes
+ifuncmod6.so-no-z-defs = yes
+tst-auditmod9a.so-no-z-defs = yes
+tst-auditmod9b.so-no-z-defs = yes
+tst-nodelete-uniquemod.so-no-z-defs = yes
+tst-nodelete-rtldmod.so-no-z-defs = yes
+tst-nodelete-zmod.so-no-z-defs = yes
+tst-nodelete2mod.so-no-z-defs = yes
+
+ifeq ($(build-shared),yes)
+# Build all the modules even when not actually running test programs.
+tests: $(test-modules)
+endif
+
+$(objpfx)loadtest: $(libdl)
+LDFLAGS-loadtest = -rdynamic
+
+$(objpfx)loadtest.out: $(test-modules)
+
+$(objpfx)neededtest: $(libdl)
+$(objpfx)neededtest.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
+			 $(objpfx)neededobj3.so
+
+$(objpfx)neededtest2: $(libdl)
+$(objpfx)neededtest2.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
+			  $(objpfx)neededobj3.so
+
+$(objpfx)neededtest3: $(libdl)
+$(objpfx)neededtest3.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
+			  $(objpfx)neededobj3.so $(objpfx)neededobj4.so
+
+$(objpfx)neededtest4: $(libdl) $(objpfx)neededobj1.so
+$(objpfx)neededtest4.out: $(objpfx)neededobj5.so $(objpfx)neededobj6.so
+
+$(objpfx)restest1: $(objpfx)testobj1.so $(objpfx)testobj1_1.so $(libdl)
+LDFLAGS-restest1 = -rdynamic
+
+$(objpfx)restest2: $(libdl)
+LDFLAGS-restest2 = -rdynamic
+
+$(objpfx)restest1.out: $(test-modules)
+
+preloadtest-preloads = testobj1 testobj2 testobj3 testobj4 testobj5
+$(objpfx)preloadtest: $(objpfx)testobj6.so
+LDFLAGS-preloadtest = -rdynamic
+$(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so)
+preloadtest-ENV = \
+  LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
+
+$(objpfx)loadfail: $(libdl)
+LDFLAGS-loadfail = -rdynamic
+
+$(objpfx)loadfail.out: $(objpfx)failobj.so
+
+$(objpfx)multiload: $(libdl)
+LDFLAGS-multiload = -rdynamic
+CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
+
+$(objpfx)multiload.out: $(objpfx)testobj1.so
+
+$(objpfx)origtest: $(libdl)
+LDFLAGS-origtest = -rdynamic
+$(objpfx)origtest.out: $(objpfx)testobj1.so
+
+ifeq ($(have-thread-library),yes)
+$(objpfx)resolvfail: $(libdl) $(shared-thread-library)
+else
+$(objpfx)resolvfail: $(libdl)
+endif
+
+$(objpfx)constload1: $(libdl)
+$(objpfx)constload1.out: $(objpfx)constload2.so $(objpfx)constload3.so
+
+$(objpfx)circleload1: $(libdl)
+$(objpfx)circleload1.out: $(objpfx)circlemod1.so \
+			  $(objpfx)circlemod1a.so
+
+$(objpfx)circlemod1.so: $(objpfx)circlemod2.so
+$(objpfx)circlemod2.so: $(objpfx)circlemod3.so
+$(objpfx)circlemod1a.so: $(objpfx)circlemod2a.so
+$(objpfx)circlemod2a.so: $(objpfx)circlemod3a.so
+
+$(objpfx)order: $(addprefix $(objpfx),dep4.so dep3.so dep2.so dep1.so)
+
+$(objpfx)order-cmp.out: $(objpfx)order.out
+	(echo "0123456789" | cmp $< -) > $@; \
+	$(evaluate-test)
+
+$(objpfx)vismain: $(addprefix $(objpfx),vismod1.so vismod2.so)
+$(objpfx)vismain.out: $(addprefix $(objpfx),vismod3.so)
+vismain-ENV = LD_PRELOAD=$(addprefix $(objpfx),vismod3.so)
+
+$(objpfx)noload: $(objpfx)testobj1.so $(libdl)
+LDFLAGS-noload = -rdynamic $(no-as-needed)
+$(objpfx)noload.out: $(objpfx)testobj5.so
+
+$(objpfx)noload-mem.out: $(objpfx)noload.out
+	$(common-objpfx)malloc/mtrace $(objpfx)noload.mtrace > $@; \
+	$(evaluate-test)
+noload-ENV = MALLOC_TRACE=$(objpfx)noload.mtrace
+
+LDFLAGS-nodelete = -rdynamic
+LDFLAGS-nodelmod1.so = -Wl,--enable-new-dtags,-z,nodelete
+LDFLAGS-nodelmod4.so = -Wl,--enable-new-dtags,-z,nodelete
+$(objpfx)nodelete: $(libdl)
+$(objpfx)nodelete.out: $(objpfx)nodelmod1.so $(objpfx)nodelmod2.so \
+		       $(objpfx)nodelmod3.so
+
+LDFLAGS-nodlopenmod.so = -Wl,--enable-new-dtags,-z,nodlopen
+$(objpfx)nodlopen: $(libdl)
+$(objpfx)nodlopen.out: $(objpfx)nodlopenmod.so
+
+$(objpfx)nodlopenmod2.so: $(objpfx)nodlopenmod.so
+$(objpfx)nodlopen2: $(libdl)
+$(objpfx)nodlopen2.out: $(objpfx)nodlopenmod2.so
+
+$(objpfx)filtmod1.so: $(objpfx)filtmod1.os $(objpfx)filtmod2.so
+	$(LINK.o) -shared -o $@ -B$(csu-objpfx) $(LDFLAGS.so) \
+		  -L$(subst :, -L,$(rpath-link)) \
+		  -Wl,-rpath-link=$(rpath-link) \
+		  $< -Wl,-F,$(objpfx)filtmod2.so
+$(objpfx)filter: $(objpfx)filtmod1.so
+
+# This does not link against libc.
+CFLAGS-filtmod1.c = $(no-stack-protector)
+
+$(objpfx)unload: $(libdl)
+$(objpfx)unload.out: $(objpfx)unloadmod.so
+
+$(objpfx)reldep: $(libdl)
+$(objpfx)reldep.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod2.so
+
+$(objpfx)reldep2: $(libdl)
+$(objpfx)reldep2.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod3.so
+
+$(objpfx)reldep3: $(libdl)
+$(objpfx)reldep3.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod4.so
+
+$(objpfx)reldep4: $(libdl)
+$(objpfx)reldep4.out: $(objpfx)reldep4mod1.so $(objpfx)reldep4mod2.so
+
+$(objpfx)next: $(objpfx)nextmod1.so $(objpfx)nextmod2.so $(libdl)
+LDFLAGS-next = $(no-as-needed)
+
+$(objpfx)unload2: $(libdl)
+$(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so
+
+$(objpfx)lateglobal: $(libdl)
+$(objpfx)lateglobal.out: $(objpfx)ltglobmod1.so $(objpfx)ltglobmod2.so
+
+$(objpfx)tst-pathopt: $(libdl)
+$(objpfx)tst-pathopt.out: tst-pathopt.sh $(objpfx)tst-pathopt \
+			  $(objpfx)pathoptobj.so
+	$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' \
+		 '$(run-program-env)'; \
+	$(evaluate-test)
+
+$(objpfx)tst-rtld-load-self.out: tst-rtld-load-self.sh $(objpfx)ld.so
+	$(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
+	$(evaluate-test)
+
+$(objpfx)initfirst: $(libdl)
+$(objpfx)initfirst.out: $(objpfx)firstobj.so
+
+$(objpfx)global: $(objpfx)globalmod1.so
+$(objpfx)global.out: $(objpfx)reldepmod1.so
+
+$(objpfx)dblload: $(libdl)
+$(objpfx)dblload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so
+
+$(objpfx)dblunload: $(libdl)
+$(objpfx)dblunload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so
+
+$(objpfx)reldep5: $(libdl)
+$(objpfx)reldep5.out: $(objpfx)reldepmod5.so $(objpfx)reldepmod6.so
+
+$(objpfx)reldep6: $(libdl)
+$(objpfx)reldep6.out: $(objpfx)reldep6mod3.so $(objpfx)reldep6mod4.so
+
+$(objpfx)reldep7: $(libdl)
+$(objpfx)reldep7.out: $(objpfx)reldep7mod1.so $(objpfx)reldep7mod2.so
+
+$(objpfx)reldep8: $(libdl)
+$(objpfx)reldep8.out: $(objpfx)reldep8mod3.so
+
+LDFLAGS-nodel2mod2.so = -Wl,--enable-new-dtags,-z,nodelete
+$(objpfx)nodelete2: $(libdl)
+$(objpfx)nodelete2.out: $(objpfx)nodel2mod3.so
+
+$(objpfx)reldep9: $(libdl)
+$(objpfx)reldep9.out: $(objpfx)reldep9mod3.so
+
+$(objpfx)tst-tls3: $(objpfx)tst-tlsmod1.so
+
+$(objpfx)tst-tls4: $(libdl)
+$(objpfx)tst-tls4.out: $(objpfx)tst-tlsmod2.so
+
+$(objpfx)tst-tls5: $(libdl)
+$(objpfx)tst-tls5.out: $(objpfx)tst-tlsmod2.so
+
+$(objpfx)tst-tls6: $(libdl)
+$(objpfx)tst-tls6.out: $(objpfx)tst-tlsmod2.so
+
+$(objpfx)tst-tls7: $(libdl)
+$(objpfx)tst-tls7.out: $(objpfx)tst-tlsmod3.so
+
+$(objpfx)tst-tls8: $(libdl)
+$(objpfx)tst-tls8.out: $(objpfx)tst-tlsmod3.so $(objpfx)tst-tlsmod4.so
+
+$(objpfx)tst-tls9: $(libdl)
+$(objpfx)tst-tls9.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
+
+$(objpfx)tst-tls10: $(objpfx)tst-tlsmod8.so $(objpfx)tst-tlsmod7.so
+
+$(objpfx)tst-tls11: $(objpfx)tst-tlsmod10.so $(objpfx)tst-tlsmod9.so
+
+$(objpfx)tst-tls12: $(objpfx)tst-tlsmod12.so $(objpfx)tst-tlsmod11.so
+
+$(objpfx)tst-tls13: $(libdl)
+$(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so
+
+$(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl)
+$(objpfx)tst-tls14.out: $(objpfx)tst-tlsmod14b.so
+
+$(objpfx)tst-tls15: $(libdl)
+$(objpfx)tst-tls15.out: $(objpfx)tst-tlsmod15a.so $(objpfx)tst-tlsmod15b.so
+
+$(objpfx)tst-tls-dlinfo: $(libdl)
+$(objpfx)tst-tls-dlinfo.out: $(objpfx)tst-tlsmod2.so
+
+
+
+$(objpfx)tst-tls16: $(libdl)
+$(objpfx)tst-tls16.out: $(objpfx)tst-tlsmod16a.so $(objpfx)tst-tlsmod16b.so
+
+$(objpfx)tst-tls17: $(libdl)
+$(objpfx)tst-tls17.out: $(objpfx)tst-tlsmod17b.so
+$(patsubst %,$(objpfx)%.os,$(tlsmod17a-modules)): $(objpfx)tst-tlsmod17a%.os: tst-tlsmod17a.c
+	$(compile-command.c) -DN=$*
+$(patsubst %,$(objpfx)%.so,$(tlsmod17a-modules)): $(objpfx)tst-tlsmod17a%.so: $(objpfx)ld.so
+$(objpfx)tst-tlsmod17b.so: $(patsubst %,$(objpfx)%.so,$(tlsmod17a-modules))
+
+$(objpfx)tst-tls18: $(libdl)
+$(objpfx)tst-tls18.out: $(patsubst %,$(objpfx)%.so,$(tlsmod18a-modules))
+$(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : tst-tlsmod18a.c
+	$(compile-command.c) -DN=$*
+$(patsubst %,$(objpfx)%.so,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so
+
+$(objpfx)tst-tls19: $(libdl)
+$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so
+
+CFLAGS-tst-align.c = $(stack-align-test-flags)
+CFLAGS-tst-align2.c = $(stack-align-test-flags)
+CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
+CFLAGS-tst-alignmod2.c = $(stack-align-test-flags)
+$(objpfx)tst-align: $(libdl)
+$(objpfx)tst-align.out: $(objpfx)tst-alignmod.so
+$(objpfx)tst-align2: $(objpfx)tst-alignmod2.so
+
+$(objpfx)unload3: $(libdl)
+$(objpfx)unload3.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
+		      $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so
+
+$(objpfx)unload4: $(libdl)
+$(objpfx)unload4.out: $(objpfx)unload4mod1.so $(objpfx)unload4mod3.so
+
+$(objpfx)unload5: $(libdl)
+$(objpfx)unload5.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
+		      $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so
+
+$(objpfx)unload6: $(libdl)
+$(objpfx)unload6.out: $(objpfx)unload6mod1.so $(objpfx)unload6mod2.so \
+		      $(objpfx)unload6mod3.so
+
+$(objpfx)unload7: $(libdl)
+$(objpfx)unload7.out: $(objpfx)unload7mod1.so $(objpfx)unload7mod2.so
+unload7-ENV = MALLOC_PERTURB_=85
+
+$(objpfx)unload8: $(libdl)
+$(objpfx)unload8.out: $(objpfx)unload8mod1.so $(objpfx)unload8mod1x.so
+
+ifdef libdl
+$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
+$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
+endif
+
+ifeq ($(have-z-execstack),yes)
+$(objpfx)tst-execstack: $(libdl)
+$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
+CPPFLAGS-tst-execstack.c = -DUSE_PTHREADS=0
+LDFLAGS-tst-execstack = -Wl,-z,noexecstack
+LDFLAGS-tst-execstack-mod = -Wl,-z,execstack
+
+$(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
+LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
+
+LDFLAGS-tst-execstack-prog = -Wl,-z,execstack
+CFLAGS-tst-execstack-prog.c += -Wno-trampolines
+CFLAGS-tst-execstack-mod.c += -Wno-trampolines
+endif
+
+LDFLAGS-tst-array2 = $(no-as-needed)
+LDFLAGS-tst-array5 = $(no-as-needed)
+
+$(objpfx)tst-array1-cmp.out: tst-array1.exp $(objpfx)tst-array1.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array1-static-cmp.out: tst-array1.exp \
+				    $(objpfx)tst-array1-static.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array2: $(objpfx)tst-array2dep.so
+$(objpfx)tst-array2-cmp.out: tst-array2.exp $(objpfx)tst-array2.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array3-cmp.out: tst-array1.exp $(objpfx)tst-array3.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array4: $(libdl)
+$(objpfx)tst-array4.out: $(objpfx)tst-array2dep.so
+$(objpfx)tst-array4-cmp.out: tst-array4.exp $(objpfx)tst-array4.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array5: $(objpfx)tst-array5dep.so
+$(objpfx)tst-array5-cmp.out: tst-array5.exp $(objpfx)tst-array5.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
+				$(objpfx)tst-array5-static.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+CFLAGS-tst-pie1.c += $(pie-ccflag)
+CFLAGS-tst-pie2.c += $(pie-ccflag)
+
+$(objpfx)tst-piemod1.so: $(libsupport)
+$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
+
+ifeq (yes,$(build-shared))
+all-built-dso := $(common-objpfx)elf/ld.so $(common-objpfx)libc.so \
+		 $(filter-out $(common-objpfx)linkobj/libc.so, \
+			      $(sort $(wildcard $(addprefix $(common-objpfx), \
+							    */lib*.so \
+							    iconvdata/*.so))))
+
+$(all-built-dso:=.dyn): %.dyn: %
+	@rm -f $@T
+	LC_ALL=C $(READELF) -W -d $< > $@T
+	test -s $@T
+	mv -f $@T $@
+common-generated += $(all-built-dso:$(common-objpfx)%=%.dyn)
+
+$(objpfx)check-textrel.out: $(..)scripts/check-textrel.awk \
+			    $(all-built-dso:=.dyn)
+	LC_ALL=C $(AWK) -f $^ > $@; \
+	$(evaluate-test)
+generated += check-textrel.out
+
+$(objpfx)execstack-default: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h)))
+	$(make-target-directory)
+	{ echo '#include <elf.h>'; \
+	  echo '#include <stackinfo.h>'; \
+	  echo '#if (DEFAULT_STACK_PERMS & PF_X) == 0'; \
+	  echo '@@@execstack-no@@@'; \
+	  echo '#else'; \
+	  echo '@@@execstack-yes@@@'; \
+	  echo '#endif'; } | \
+	$(CC) $(CFLAGS) $(CPPFLAGS) -E -x c-header - | \
+	sed -n -e 's/^@@@\(.*\)@@@/\1/p' > $@T
+	mv -f $@T $@
+generated += execstack-default
+
+$(all-built-dso:=.phdr): %.phdr: %
+	@rm -f $@T
+	LC_ALL=C $(READELF) -W -l $< > $@T
+	test -s $@T
+	mv -f $@T $@
+common-generated += $(all-built-dso:$(common-objpfx)%=%.phdr)
+
+$(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \
+			      $(objpfx)execstack-default \
+			      $(all-built-dso:=.phdr)
+	LC_ALL=C $(AWK) -f $^ > $@; \
+	$(evaluate-test)
+generated += check-execstack.out
+
+$(objpfx)tst-dlmodcount: $(libdl)
+$(objpfx)tst-dlmodcount.out: $(test-modules)
+
+$(all-built-dso:=.jmprel): %.jmprel: % Makefile
+	@rm -f $@T
+	LC_ALL=C $(READELF) -W -S -d -r $< > $@T
+	test -s $@T
+	mv -f $@T $@
+common-generated += $(all-built-dso:$(common-objpfx)%=%.jmprel)
+
+localplt-built-dso := $(addprefix $(common-objpfx),\
+				  libc.so \
+				  elf/ld.so \
+				  math/libm.so \
+				  rt/librt.so \
+				  dlfcn/libdl.so \
+				  resolv/libresolv.so \
+				  crypt/libcrypt.so \
+		       )
+ifeq ($(build-mathvec),yes)
+localplt-built-dso += $(addprefix $(common-objpfx), mathvec/libmvec.so)
+endif
+ifeq ($(have-thread-library),yes)
+localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
+endif
+
+vpath localplt.data $(+sysdep_dirs)
+
+$(objpfx)check-localplt.out: $(..)scripts/check-localplt.awk \
+			     $(..)scripts/localplt.awk \
+			     $(localplt-built-dso:=.jmprel) \
+			     localplt.data
+	LC_ALL=C $(AWK) -f $(filter-out $< %localplt.data,$^) | \
+	  LC_ALL=C $(AWK) -f $< $(filter %localplt.data,$^) - \
+	  > $@; \
+	$(evaluate-test)
+endif
+
+$(objpfx)tst-dlopenrpathmod.so: $(libdl)
+$(objpfx)tst-dlopenrpath: $(objpfx)tst-dlopenrpathmod.so $(libdl)
+CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\"
+LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir
+$(objpfx)tst-dlopenrpath.out: $(objpfx)firstobj.so
+
+$(objpfx)tst-deep1mod2.so: $(objpfx)tst-deep1mod3.so
+$(objpfx)tst-deep1: $(libdl) $(objpfx)tst-deep1mod1.so
+$(objpfx)tst-deep1.out: $(objpfx)tst-deep1mod2.so
+LDFLAGS-tst-deep1 += -rdynamic
+tst-deep1mod3.so-no-z-defs = yes
+
+$(objpfx)tst-dlmopen1mod.so: $(libdl)
+$(objpfx)tst-dlmopen1: $(libdl)
+$(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so
+
+$(objpfx)tst-dlmopen2: $(libdl)
+$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
+
+$(objpfx)tst-dlmopen3: $(libdl)
+$(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
+
+$(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
+tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+
+$(objpfx)tst-audit2: $(libdl)
+$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so $(objpfx)tst-auditmod9b.so
+# Prevent GCC-5 from translating a malloc/memset pair into calloc
+CFLAGS-tst-audit2.c += -fno-builtin
+tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+
+$(objpfx)tst-audit9: $(libdl)
+$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so
+tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so
+
+$(objpfx)tst-audit8: $(libm)
+$(objpfx)tst-audit8.out: $(objpfx)tst-auditmod1.so
+tst-audit8-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+
+$(objpfx)tst-global1: $(libdl)
+$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
+
+$(objpfx)order2: $(libdl)
+$(objpfx)order2.out: $(objpfx)order2mod1.so $(objpfx)order2mod2.so
+$(objpfx)order2-cmp.out: $(objpfx)order2.out
+	(echo "12345" | cmp $< -) > $@; \
+	$(evaluate-test)
+$(objpfx)order2mod1.so: $(objpfx)order2mod4.so
+$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
+$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
+order2mod2.so-no-z-defs = yes
+LDFLAGS-order2mod1.so = $(no-as-needed)
+LDFLAGS-order2mod2.so = $(no-as-needed)
+
+tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
+tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
+
+tst-ptrguard1-ARGS = --command "$(host-test-program-cmd) --child"
+# When built statically, the pointer guard interface uses
+# __pointer_chk_guard_local.
+CFLAGS-tst-ptrguard1-static.c = -DPTRGUARD_LOCAL
+tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child"
+
+$(objpfx)tst-leaks1: $(libdl)
+$(objpfx)tst-leaks1-mem.out: $(objpfx)tst-leaks1.out
+	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-leaks1-static: $(common-objpfx)dlfcn/libdl.a
+$(objpfx)tst-leaks1-static-mem.out: $(objpfx)tst-leaks1-static.out
+	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1-static.mtrace > $@; \
+	$(evaluate-test)
+
+tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
+tst-leaks1-static-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1-static.mtrace
+
+$(objpfx)tst-addr1: $(libdl)
+
+$(objpfx)tst-thrlock: $(libdl) $(shared-thread-library)
+$(objpfx)tst-dlopen-aout: $(libdl) $(shared-thread-library)
+
+CFLAGS-ifuncmain1pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain1picstatic.c += $(pic-ccflag)
+CFLAGS-ifuncmain1staticpic.c += $(pic-ccflag)
+CFLAGS-ifuncdep1pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain1vispic.c += $(pic-ccflag)
+CFLAGS-ifuncmain2pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain2picstatic.c += $(pic-ccflag)
+CFLAGS-ifuncdep2pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain4picstatic.c += $(pic-ccflag)
+CFLAGS-ifuncmain5pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain5picstatic.c += $(pic-ccflag)
+CFLAGS-ifuncmain5staticpic.c += $(pic-ccflag)
+CFLAGS-ifuncdep5pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain7pic.c += $(pic-ccflag)
+CFLAGS-ifuncmain7picstatic.c += $(pic-ccflag)
+
+LDFLAGS-ifuncmain3 = -Wl,-export-dynamic
+
+CFLAGS-ifuncmain1pie.c += $(pie-ccflag)
+CFLAGS-ifuncmain1vispie.c += $(pie-ccflag)
+CFLAGS-ifuncmain1staticpie.c += $(pie-ccflag)
+CFLAGS-ifuncmain5pie.c += $(pie-ccflag)
+CFLAGS-ifuncmain6pie.c += $(pie-ccflag)
+CFLAGS-ifuncmain7pie.c += $(pie-ccflag)
+
+$(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so
+$(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o
+$(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so
+$(objpfx)ifuncmain5pie: $(objpfx)ifuncmod5.so
+$(objpfx)ifuncmain6pie: $(objpfx)ifuncmod6.so
+
+$(objpfx)ifuncmain1: $(addprefix $(objpfx),ifuncmod1.so)
+$(objpfx)ifuncmain1pic: $(addprefix $(objpfx),ifuncmod1.so)
+$(objpfx)ifuncmain1staticpic: $(addprefix $(objpfx),ifuncdep1pic.o)
+$(objpfx)ifuncmain1static: $(addprefix $(objpfx),ifuncdep1.o)
+$(objpfx)ifuncmain1picstatic: $(addprefix $(objpfx),ifuncdep1pic.o)
+$(objpfx)ifuncmain1vis: $(addprefix $(objpfx),ifuncmod1.so)
+$(objpfx)ifuncmain1vispic: $(addprefix $(objpfx),ifuncmod1.so)
+$(objpfx)ifuncmain2: $(addprefix $(objpfx),ifuncdep2.o)
+$(objpfx)ifuncmain2pic: $(addprefix $(objpfx),ifuncdep2pic.o)
+$(objpfx)ifuncmain2static: $(addprefix $(objpfx),ifuncdep2.o)
+$(objpfx)ifuncmain2picstatic: $(addprefix $(objpfx),ifuncdep2pic.o)
+
+$(objpfx)ifuncmain3: $(libdl)
+$(objpfx)ifuncmain3.out: $(objpfx)ifuncmod3.so
+
+$(objpfx)ifuncmain5: $(addprefix $(objpfx),ifuncmod5.so)
+$(objpfx)ifuncmain5pic: $(addprefix $(objpfx),ifuncmod5.so)
+$(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o)
+$(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o)
+$(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o)
+
+$(objpfx)tst-unique1: $(libdl)
+$(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
+			  $(objpfx)tst-unique1mod2.so
+
+$(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so
+$(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so
+
+$(objpfx)tst-unique3: $(libdl) $(objpfx)tst-unique3lib.so
+$(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so
+
+$(objpfx)tst-unique4: $(objpfx)tst-unique4lib.so
+
+$(objpfx)tst-nodelete: $(libdl)
+$(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \
+			   $(objpfx)tst-nodelete-rtldmod.so \
+			   $(objpfx)tst-nodelete-zmod.so
+
+LDFLAGS-tst-nodelete = -rdynamic
+LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete
+
+$(objpfx)tst-nodelete2: $(libdl)
+$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so
+
+LDFLAGS-tst-nodelete2 = -rdynamic
+
+$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-initorder2: $(objpfx)tst-initorder2a.so $(objpfx)tst-initorder2d.so $(objpfx)tst-initorder2c.so
+$(objpfx)tst-initorder2a.so: $(objpfx)tst-initorder2b.so
+$(objpfx)tst-initorder2b.so: $(objpfx)tst-initorder2c.so
+$(objpfx)tst-initorder2c.so: $(objpfx)tst-initorder2d.so
+LDFLAGS-tst-initorder2 = $(no-as-needed)
+LDFLAGS-tst-initorder2a.so = $(no-as-needed)
+LDFLAGS-tst-initorder2b.so = $(no-as-needed)
+LDFLAGS-tst-initorder2c.so = $(no-as-needed)
+define o-iterator-doit
+$(objpfx)tst-initorder2$o.os: tst-initorder2.c; \
+$$(compile-command.c) -DNAME=\"$o\"
+endef
+object-suffixes-left := a b c d
+include $(o-iterator)
+
+$(objpfx)tst-initorder2-cmp.out: tst-initorder2.exp $(objpfx)tst-initorder2.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-relsort1: $(libdl)
+$(objpfx)tst-relsort1mod1.so: $(libm) $(objpfx)tst-relsort1mod2.so
+$(objpfx)tst-relsort1mod2.so: $(libm)
+$(objpfx)tst-relsort1.out: $(objpfx)tst-relsort1mod1.so \
+			   $(objpfx)tst-relsort1mod2.so
+
+$(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so
+	$(test-wrapper-env) \
+	LD_TRACE_LOADED_OBJECTS=1 \
+	LD_DEBUG=unused \
+	LD_PRELOAD= \
+	$(rtld-prefix) \
+	  $< > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out
+	cmp $< /dev/null > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-audit11.out: $(objpfx)tst-auditmod11.so $(objpfx)tst-audit11mod1.so
+$(objpfx)tst-audit11: $(libdl)
+tst-audit11-ENV = LD_AUDIT=$(objpfx)tst-auditmod11.so
+$(objpfx)tst-audit11mod1.so: $(objpfx)tst-audit11mod2.so
+LDFLAGS-tst-audit11mod2.so = -Wl,--version-script=tst-audit11mod2.map,-soname,tst-audit11mod2.so
+
+$(objpfx)tst-audit12.out: $(objpfx)tst-auditmod12.so $(objpfx)tst-audit12mod1.so $(objpfx)tst-audit12mod3.so
+$(objpfx)tst-audit12: $(libdl)
+tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so
+$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so
+LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map
+
+# Override -z defs, so that we can reference an undefined symbol.
+# Force lazy binding for the same reason.
+LDFLAGS-tst-latepthreadmod.so = \
+  -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
+# Do not optimize sibling calls as the test relies on a JMP_SLOT relocation for
+# function this_function_is_not_defined.
+CFLAGS-tst-latepthreadmod.c = -fno-optimize-sibling-calls
+$(objpfx)tst-latepthreadmod.so: $(shared-thread-library)
+$(objpfx)tst-latepthread: $(libdl)
+$(objpfx)tst-latepthread.out: $(objpfx)tst-latepthreadmod.so
+
+# The test modules are parameterized by preprocessor macros.
+$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules)): \
+  $(objpfx)tst-tls-manydynamic%mod.os : tst-tls-manydynamicmod.c
+	$(compile-command.c) \
+	  -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$*
+$(objpfx)tst-tls-manydynamic: $(libdl) $(shared-thread-library)
+$(objpfx)tst-tls-manydynamic.out: \
+  $(patsubst %,$(objpfx)%.so,$(tst-tls-many-dynamic-modules))
+
+tst-prelink-ENV = LD_TRACE_PRELINKING=1
+
+$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out
+	grep stdout $< | grep conflict | $(AWK) '{ print $$10, $$11 }' > $@
+
+$(objpfx)tst-prelink-cmp.out: tst-prelink.exp \
+			      $(objpfx)tst-prelink-conflict.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
+	$(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
+		 '$(run-program-env)' > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-dlsym-error: $(libdl)
+
+# Test static linking of all the libraries we can possibly link
+# together.  Note that in some configurations this may be less than the
+# complete list of libraries we build but we try to maxmimize this list.
+$(objpfx)tst-linkall-static: \
+  $(common-objpfx)math/libm.a \
+  $(common-objpfx)resolv/libresolv.a \
+  $(common-objpfx)dlfcn/libdl.a \
+  $(common-objpfx)login/libutil.a \
+  $(common-objpfx)rt/librt.a \
+  $(common-objpfx)resolv/libanl.a \
+  $(static-thread-library)
+
+# If we are using NSS crypto and we have the ability to link statically
+# then we include libcrypt.a, otherwise we leave out libcrypt.a and
+# link as much as we can into the tst-linkall-static test.  This assumes
+# that linking with libcrypt.a does everything required to include the
+# static NSS crypto library.
+ifeq (yesyes,$(nss-crypt)$(static-nss-crypt))
+$(objpfx)tst-linkall-static: \
+  $(common-objpfx)crypt/libcrypt.a
+endif
+# If we are not using NSS crypto then we always have the ability to link
+# with libcrypt.a.
+ifeq (no,$(nss-crypt))
+$(objpfx)tst-linkall-static: \
+  $(common-objpfx)crypt/libcrypt.a
+endif
+
+# The application depends on the DSO, and the DSO loads the plugin.
+# The plugin also depends on the DSO. This creates the circular
+# dependency via dlopen that we're testing to make sure works.
+$(objpfx)tst-nodelete-dlclose-dso.so: $(libdl)
+$(objpfx)tst-nodelete-dlclose-plugin.so: $(objpfx)tst-nodelete-dlclose-dso.so
+$(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so
+$(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
+				   $(objpfx)tst-nodelete-dlclose-plugin.so
+
+tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
+		     LD_HWCAP_MASK=0x1
+tst-env-setuid-tunables-ENV = \
+	GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
diff --git a/REORG.TODO/elf/Versions b/REORG.TODO/elf/Versions
new file mode 100644
index 0000000000..c59facdbd7
--- /dev/null
+++ b/REORG.TODO/elf/Versions
@@ -0,0 +1,77 @@
+libc {
+  GLIBC_2.0 {
+%ifdef EXPORT_UNWIND_FIND_FDE
+    __deregister_frame_info; __register_frame_info;
+%endif
+  }
+  GLIBC_2.1 {
+    # functions used in other libraries
+    _dl_mcount_wrapper; _dl_mcount_wrapper_check;
+  }
+  GLIBC_2.2.4 {
+    dl_iterate_phdr;
+  }
+%ifdef EXPORT_UNWIND_FIND_FDE
+  # Needed for SHLIB_COMPAT calls using this version.
+  GLIBC_2.2.5 {
+  }
+  GCC_3.0 {
+    __deregister_frame_info_bases; __register_frame_info_bases;
+    __register_frame_info_table_bases; _Unwind_Find_FDE;
+  }
+%endif
+  GLIBC_PRIVATE {
+    # functions used in other libraries
+    _dl_addr;
+    _dl_open_hook;
+    _dl_sym; _dl_vsym;
+    __libc_dlclose; __libc_dlopen_mode; __libc_dlsym;
+
+    # Internal error handling support.  Interposes the functions in ld.so.
+    _dl_signal_error; _dl_catch_error;
+  }
+}
+
+ld {
+  GLIBC_2.0 {
+    # Functions which are interposed from libc.so.
+    calloc; free; malloc; realloc;
+
+    _r_debug;
+  }
+  GLIBC_2.1 {
+    # functions used in other libraries
+    _dl_mcount;
+    # historically used by Garbage Collectors
+    __libc_stack_end;
+  }
+  GLIBC_2.3 {
+    # runtime interface to TLS
+    __tls_get_addr;
+  }
+  GLIBC_2.4 {
+    # stack canary
+    __stack_chk_guard;
+  }
+  GLIBC_PRIVATE {
+    # Those are in the dynamic linker, but used by libc.so.
+    __libc_enable_secure;
+    _dl_allocate_tls; _dl_allocate_tls_init;
+    _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
+    _dl_deallocate_tls; _dl_make_stack_executable; _dl_out_of_memory;
+    _dl_rtld_di_serinfo; _dl_starting_up;
+    _rtld_global; _rtld_global_ro;
+
+    # Only here for gdb while a better method is developed.
+    _dl_debug_state;
+
+    # Pointer protection.
+    __pointer_chk_guard;
+
+    # Internal error handling support.  Interposed by libc.so.
+    _dl_signal_error; _dl_catch_error;
+
+    # Set value of a tunable.
+    __tunable_get_val;
+  }
+}
diff --git a/REORG.TODO/elf/cache.c b/REORG.TODO/elf/cache.c
new file mode 100644
index 0000000000..a76f89281d
--- /dev/null
+++ b/REORG.TODO/elf/cache.c
@@ -0,0 +1,829 @@
+/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>, 1999.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <dirent.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ldconfig.h>
+#include <dl-cache.h>
+
+struct cache_entry
+{
+  char *lib;			/* Library name.  */
+  char *path;			/* Path to find library.  */
+  int flags;			/* Flags to indicate kind of library.  */
+  unsigned int osversion;	/* Required OS version.  */
+  uint64_t hwcap;		/* Important hardware capabilities.  */
+  int bits_hwcap;		/* Number of bits set in hwcap.  */
+  struct cache_entry *next;	/* Next entry in list.  */
+};
+
+/* List of all cache entries.  */
+static struct cache_entry *entries;
+
+static const char *flag_descr[] =
+{ "libc4", "ELF", "libc5", "libc6"};
+
+/* Print a single entry.  */
+static void
+print_entry (const char *lib, int flag, unsigned int osversion,
+	     uint64_t hwcap, const char *key)
+{
+  printf ("\t%s (", lib);
+  switch (flag & FLAG_TYPE_MASK)
+    {
+    case FLAG_LIBC4:
+    case FLAG_ELF:
+    case FLAG_ELF_LIBC5:
+    case FLAG_ELF_LIBC6:
+      fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
+      break;
+    default:
+      fputs (_("unknown"), stdout);
+      break;
+    }
+  switch (flag & FLAG_REQUIRED_MASK)
+    {
+    case FLAG_SPARC_LIB64:
+      fputs (",64bit", stdout);
+      break;
+    case FLAG_IA64_LIB64:
+      fputs (",IA-64", stdout);
+      break;
+    case FLAG_X8664_LIB64:
+      fputs (",x86-64", stdout);
+      break;
+    case FLAG_S390_LIB64:
+      fputs (",64bit", stdout);
+      break;
+    case FLAG_POWERPC_LIB64:
+      fputs (",64bit", stdout);
+      break;
+    case FLAG_MIPS64_LIBN32:
+      fputs (",N32", stdout);
+      break;
+    case FLAG_MIPS64_LIBN64:
+      fputs (",64bit", stdout);
+      break;
+    case FLAG_X8664_LIBX32:
+      fputs (",x32", stdout);
+      break;
+    case FLAG_ARM_LIBHF:
+      fputs (",hard-float", stdout);
+      break;
+    case FLAG_AARCH64_LIB64:
+      fputs (",AArch64", stdout);
+      break;
+    /* Uses the ARM soft-float ABI.  */
+    case FLAG_ARM_LIBSF:
+      fputs (",soft-float", stdout);
+      break;
+    case FLAG_MIPS_LIB32_NAN2008:
+      fputs (",nan2008", stdout);
+      break;
+    case FLAG_MIPS64_LIBN32_NAN2008:
+      fputs (",N32,nan2008", stdout);
+      break;
+    case FLAG_MIPS64_LIBN64_NAN2008:
+      fputs (",64bit,nan2008", stdout);
+      break;
+    case 0:
+      break;
+    default:
+      printf (",%d", flag & FLAG_REQUIRED_MASK);
+      break;
+    }
+  if (hwcap != 0)
+    printf (", hwcap: %#.16" PRIx64, hwcap);
+  if (osversion != 0)
+    {
+      static const char *const abi_tag_os[] =
+      {
+	[0] = "Linux",
+	[1] = "Hurd",
+	[2] = "Solaris",
+	[3] = "FreeBSD",
+	[4] = "kNetBSD",
+	[5] = "Syllable",
+	[6] = N_("Unknown OS")
+      };
+#define MAXTAG (sizeof abi_tag_os / sizeof abi_tag_os[0] - 1)
+      unsigned int os = osversion >> 24;
+
+      printf (_(", OS ABI: %s %d.%d.%d"),
+	      _(abi_tag_os[os > MAXTAG ? MAXTAG : os]),
+	      (osversion >> 16) & 0xff,
+	      (osversion >> 8) & 0xff,
+	      osversion & 0xff);
+    }
+  printf (") => %s\n", key);
+}
+
+
+/* Print the whole cache file, if a file contains the new cache format
+   hidden in the old one, print the contents of the new format.  */
+void
+print_cache (const char *cache_name)
+{
+  int fd = open (cache_name, O_RDONLY);
+  if (fd < 0)
+    error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
+
+  struct stat64 st;
+  if (fstat64 (fd, &st) < 0
+      /* No need to map the file if it is empty.  */
+      || st.st_size == 0)
+    {
+      close (fd);
+      return;
+    }
+
+  struct cache_file *cache
+    = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (cache == MAP_FAILED)
+    error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
+
+  size_t cache_size = st.st_size;
+  if (cache_size < sizeof (struct cache_file))
+    error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
+
+  struct cache_file_new *cache_new = NULL;
+  const char *cache_data;
+  int format = 0;
+
+  if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
+    {
+      /* This can only be the new format without the old one.  */
+      cache_new = (struct cache_file_new *) cache;
+
+      if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
+	  || memcmp (cache_new->version, CACHE_VERSION,
+		      sizeof CACHE_VERSION - 1))
+	error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
+      format = 1;
+      /* This is where the strings start.  */
+      cache_data = (const char *) cache_new;
+    }
+  else
+    {
+      size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
+				   + (cache->nlibs
+				      * sizeof (struct file_entry)));
+      /* This is where the strings start.  */
+      cache_data = (const char *) &cache->libs[cache->nlibs];
+
+      /* Check for a new cache embedded in the old format.  */
+      if (cache_size >
+	  (offset + sizeof (struct cache_file_new)))
+	{
+
+	  cache_new = (struct cache_file_new *) ((void *)cache + offset);
+
+	  if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
+		      sizeof CACHEMAGIC_NEW - 1) == 0
+	      && memcmp (cache_new->version, CACHE_VERSION,
+			 sizeof CACHE_VERSION - 1) == 0)
+	    {
+	      cache_data = (const char *) cache_new;
+	      format = 1;
+	    }
+	}
+    }
+
+  if (format == 0)
+    {
+      printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
+
+      /* Print everything.  */
+      for (unsigned int i = 0; i < cache->nlibs; i++)
+	print_entry (cache_data + cache->libs[i].key,
+		     cache->libs[i].flags, 0, 0,
+		     cache_data + cache->libs[i].value);
+    }
+  else if (format == 1)
+    {
+      printf (_("%d libs found in cache `%s'\n"),
+	      cache_new->nlibs, cache_name);
+
+      /* Print everything.  */
+      for (unsigned int i = 0; i < cache_new->nlibs; i++)
+	print_entry (cache_data + cache_new->libs[i].key,
+		     cache_new->libs[i].flags,
+		     cache_new->libs[i].osversion,
+		     cache_new->libs[i].hwcap,
+		     cache_data + cache_new->libs[i].value);
+    }
+  /* Cleanup.  */
+  munmap (cache, cache_size);
+  close (fd);
+}
+
+/* Initialize cache data structures.  */
+void
+init_cache (void)
+{
+  entries = NULL;
+}
+
+static int
+compare (const struct cache_entry *e1, const struct cache_entry *e2)
+{
+  /* We need to swap entries here to get the correct sort order.  */
+  int res = _dl_cache_libcmp (e2->lib, e1->lib);
+  if (res == 0)
+    {
+      if (e1->flags < e2->flags)
+	return 1;
+      else if (e1->flags > e2->flags)
+	return -1;
+      /* Sort by most specific hwcap.  */
+      else if (e2->bits_hwcap > e1->bits_hwcap)
+	return 1;
+      else if (e2->bits_hwcap < e1->bits_hwcap)
+	return -1;
+      else if (e2->hwcap > e1->hwcap)
+	return 1;
+      else if (e2->hwcap < e1->hwcap)
+	return -1;
+      if (e2->osversion > e1->osversion)
+	return 1;
+      if (e2->osversion < e1->osversion)
+	return -1;
+    }
+  return res;
+}
+
+/* Save the contents of the cache.  */
+void
+save_cache (const char *cache_name)
+{
+  /* The cache entries are sorted already, save them in this order. */
+
+  /* Count the length of all strings.  */
+  /* The old format doesn't contain hwcap entries and doesn't contain
+     libraries in subdirectories with hwcaps entries.  Count therefore
+     also all entries with hwcap == 0.  */
+  size_t total_strlen = 0;
+  struct cache_entry *entry;
+  /* Number of cache entries.  */
+  int cache_entry_count = 0;
+  /* Number of normal cache entries.  */
+  int cache_entry_old_count = 0;
+
+  for (entry = entries; entry != NULL; entry = entry->next)
+    {
+      /* Account the final NULs.  */
+      total_strlen += strlen (entry->lib) + strlen (entry->path) + 2;
+      ++cache_entry_count;
+      if (entry->hwcap == 0)
+	++cache_entry_old_count;
+    }
+
+  /* Create the on disk cache structure.  */
+  struct cache_file *file_entries = NULL;
+  size_t file_entries_size = 0;
+
+  if (opt_format != 2)
+    {
+      /* struct cache_file_new is 64-bit aligned on some arches while
+	 only 32-bit aligned on other arches.  Duplicate last old
+	 cache entry so that new cache in ld.so.cache can be used by
+	 both.  */
+      if (opt_format != 0)
+	cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
+
+      /* And the list of all entries in the old format.  */
+      file_entries_size = sizeof (struct cache_file)
+	+ cache_entry_old_count * sizeof (struct file_entry);
+      file_entries = xmalloc (file_entries_size);
+
+      /* Fill in the header.  */
+      memset (file_entries, '\0', sizeof (struct cache_file));
+      memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
+
+      file_entries->nlibs = cache_entry_old_count;
+    }
+
+  struct cache_file_new *file_entries_new = NULL;
+  size_t file_entries_new_size = 0;
+
+  if (opt_format != 0)
+    {
+      /* And the list of all entries in the new format.  */
+      file_entries_new_size = sizeof (struct cache_file_new)
+	+ cache_entry_count * sizeof (struct file_entry_new);
+      file_entries_new = xmalloc (file_entries_new_size);
+
+      /* Fill in the header.  */
+      memset (file_entries_new, '\0', sizeof (struct cache_file_new));
+      memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
+	      sizeof CACHEMAGIC_NEW - 1);
+      memcpy (file_entries_new->version, CACHE_VERSION,
+	      sizeof CACHE_VERSION - 1);
+
+      file_entries_new->nlibs = cache_entry_count;
+      file_entries_new->len_strings = total_strlen;
+    }
+
+  /* Pad for alignment of cache_file_new.  */
+  size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
+
+  /* If we have both formats, we hide the new format in the strings
+     table, we have to adjust all string indices for this so that
+     old libc5/glibc 2 dynamic linkers just ignore them.  */
+  unsigned int str_offset;
+  if (opt_format != 0)
+    str_offset = file_entries_new_size;
+  else
+    str_offset = 0;
+
+  /* An array for all strings.  */
+  char *strings = xmalloc (total_strlen);
+  char *str = strings;
+  int idx_old;
+  int idx_new;
+
+  for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
+       entry = entry->next, ++idx_new)
+    {
+      /* First the library.  */
+      if (opt_format != 2 && entry->hwcap == 0)
+	{
+	  file_entries->libs[idx_old].flags = entry->flags;
+	  /* XXX: Actually we can optimize here and remove duplicates.  */
+	  file_entries->libs[idx_old].key = str_offset + pad;
+	}
+      if (opt_format != 0)
+	{
+	  /* We could subtract file_entries_new_size from str_offset -
+	     not doing so makes the code easier, the string table
+	     always begins at the beginning of the new cache
+	     struct.  */
+	  file_entries_new->libs[idx_new].flags = entry->flags;
+	  file_entries_new->libs[idx_new].osversion = entry->osversion;
+	  file_entries_new->libs[idx_new].hwcap = entry->hwcap;
+	  file_entries_new->libs[idx_new].key = str_offset;
+	}
+
+      size_t len = strlen (entry->lib) + 1;
+      str = mempcpy (str, entry->lib, len);
+      str_offset += len;
+      /* Then the path.  */
+      if (opt_format != 2 && entry->hwcap == 0)
+	file_entries->libs[idx_old].value = str_offset + pad;
+      if (opt_format != 0)
+	file_entries_new->libs[idx_new].value = str_offset;
+      len = strlen (entry->path) + 1;
+      str = mempcpy (str, entry->path, len);
+      str_offset += len;
+      /* Ignore entries with hwcap for old format.  */
+      if (entry->hwcap == 0)
+	++idx_old;
+    }
+
+  /* Duplicate last old cache entry if needed.  */
+  if (opt_format != 2
+      && idx_old < cache_entry_old_count)
+    file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
+
+  /* Write out the cache.  */
+
+  /* Write cache first to a temporary file and rename it later.  */
+  char *temp_name = xmalloc (strlen (cache_name) + 2);
+  sprintf (temp_name, "%s~", cache_name);
+
+  /* Create file.  */
+  int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
+		 S_IRUSR|S_IWUSR);
+  if (fd < 0)
+    error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
+	   temp_name);
+
+  /* Write contents.  */
+  if (opt_format != 2)
+    {
+      if (write (fd, file_entries, file_entries_size)
+	  != (ssize_t) file_entries_size)
+	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+    }
+  if (opt_format != 0)
+    {
+      /* Align cache.  */
+      if (opt_format != 2)
+	{
+	  char zero[pad];
+	  memset (zero, '\0', pad);
+	  if (write (fd, zero, pad) != (ssize_t) pad)
+	    error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+	}
+      if (write (fd, file_entries_new, file_entries_new_size)
+	  != (ssize_t) file_entries_new_size)
+	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+    }
+
+  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
+      || close (fd))
+    error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+
+  /* Make sure user can always read cache file */
+  if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
+    error (EXIT_FAILURE, errno,
+	   _("Changing access rights of %s to %#o failed"), temp_name,
+	   S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
+
+  /* Move temporary to its final location.  */
+  if (rename (temp_name, cache_name))
+    error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
+	   cache_name);
+
+  /* Free all allocated memory.  */
+  free (file_entries_new);
+  free (file_entries);
+  free (strings);
+
+  while (entries)
+    {
+      entry = entries;
+      entries = entries->next;
+      free (entry);
+    }
+}
+
+
+/* Add one library to the cache.  */
+void
+add_to_cache (const char *path, const char *lib, int flags,
+	      unsigned int osversion, uint64_t hwcap)
+{
+  size_t liblen = strlen (lib) + 1;
+  size_t len = liblen + strlen (path) + 1;
+  struct cache_entry *new_entry
+    = xmalloc (sizeof (struct cache_entry) + liblen + len);
+
+  new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen);
+  new_entry->path = new_entry->lib + liblen;
+  snprintf (new_entry->path, len, "%s/%s", path, lib);
+  new_entry->flags = flags;
+  new_entry->osversion = osversion;
+  new_entry->hwcap = hwcap;
+  new_entry->bits_hwcap = 0;
+
+  /* Count the number of bits set in the masked value.  */
+  for (size_t i = 0;
+       (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
+    if ((hwcap & (1ULL << i)) != 0)
+      ++new_entry->bits_hwcap;
+
+
+  /* Keep the list sorted - search for right place to insert.  */
+  struct cache_entry *ptr = entries;
+  struct cache_entry *prev = entries;
+  while (ptr != NULL)
+    {
+      if (compare (ptr, new_entry) > 0)
+	break;
+      prev = ptr;
+      ptr = ptr->next;
+    }
+  /* Is this the first entry?  */
+  if (ptr == entries)
+    {
+      new_entry->next = entries;
+      entries = new_entry;
+    }
+  else
+    {
+      new_entry->next = prev->next;
+      prev->next = new_entry;
+    }
+}
+
+
+/* Auxiliary cache.  */
+
+struct aux_cache_entry_id
+{
+  uint64_t ino;
+  uint64_t ctime;
+  uint64_t size;
+  uint64_t dev;
+};
+
+struct aux_cache_entry
+{
+  struct aux_cache_entry_id id;
+  int flags;
+  unsigned int osversion;
+  int used;
+  char *soname;
+  struct aux_cache_entry *next;
+};
+
+#define AUX_CACHEMAGIC		"glibc-ld.so.auxcache-1.0"
+
+struct aux_cache_file_entry
+{
+  struct aux_cache_entry_id id;	/* Unique id of entry.  */
+  int32_t flags;		/* This is 1 for an ELF library.  */
+  uint32_t soname;		/* String table indice.  */
+  uint32_t osversion;		/* Required OS version.	 */
+  int32_t pad;
+};
+
+/* ldconfig maintains an auxiliary cache file that allows
+   only reading those libraries that have changed since the last iteration.
+   For this for each library some information is cached in the auxiliary
+   cache.  */
+struct aux_cache_file
+{
+  char magic[sizeof AUX_CACHEMAGIC - 1];
+  uint32_t nlibs;		/* Number of entries.  */
+  uint32_t len_strings;		/* Size of string table. */
+  struct aux_cache_file_entry libs[0]; /* Entries describing libraries.  */
+  /* After this the string table of size len_strings is found.	*/
+};
+
+static const unsigned int primes[] =
+{
+  1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
+  524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
+  67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
+};
+
+static size_t aux_hash_size;
+static struct aux_cache_entry **aux_hash;
+
+/* Simplistic hash function for aux_cache_entry_id.  */
+static unsigned int
+aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
+{
+  uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
+  return ret ^ (ret >> 32);
+}
+
+static size_t nextprime (size_t x)
+{
+  for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
+    if (primes[i] >= x)
+      return primes[i];
+  return x;
+}
+
+void
+init_aux_cache (void)
+{
+  aux_hash_size = primes[3];
+  aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
+}
+
+int
+search_aux_cache (struct stat64 *stat_buf, int *flags,
+		  unsigned int *osversion, char **soname)
+{
+  struct aux_cache_entry_id id;
+  id.ino = (uint64_t) stat_buf->st_ino;
+  id.ctime = (uint64_t) stat_buf->st_ctime;
+  id.size = (uint64_t) stat_buf->st_size;
+  id.dev = (uint64_t) stat_buf->st_dev;
+
+  unsigned int hash = aux_cache_entry_id_hash (&id);
+  struct aux_cache_entry *entry;
+  for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
+    if (id.ino == entry->id.ino
+	&& id.ctime == entry->id.ctime
+	&& id.size == entry->id.size
+	&& id.dev == entry->id.dev)
+      {
+	*flags = entry->flags;
+	*osversion = entry->osversion;
+	if (entry->soname != NULL)
+	  *soname = xstrdup (entry->soname);
+	else
+	  *soname = NULL;
+	entry->used = 1;
+	return 1;
+      }
+
+  return 0;
+}
+
+static void
+insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
+		     unsigned int osversion, const char *soname, int used)
+{
+  size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
+  struct aux_cache_entry *entry;
+  for (entry = aux_hash[hash]; entry; entry = entry->next)
+    if (id->ino == entry->id.ino
+	&& id->ctime == entry->id.ctime
+	&& id->size == entry->id.size
+	&& id->dev == entry->id.dev)
+      abort ();
+
+  size_t len = soname ? strlen (soname) + 1 : 0;
+  entry = xmalloc (sizeof (struct aux_cache_entry) + len);
+  entry->id = *id;
+  entry->flags = flags;
+  entry->osversion = osversion;
+  entry->used = used;
+  if (soname != NULL)
+    entry->soname = memcpy ((char *) (entry + 1), soname, len);
+  else
+    entry->soname = NULL;
+  entry->next = aux_hash[hash];
+  aux_hash[hash] = entry;
+}
+
+void
+add_to_aux_cache (struct stat64 *stat_buf, int flags,
+		  unsigned int osversion, const char *soname)
+{
+  struct aux_cache_entry_id id;
+  id.ino = (uint64_t) stat_buf->st_ino;
+  id.ctime = (uint64_t) stat_buf->st_ctime;
+  id.size = (uint64_t) stat_buf->st_size;
+  id.dev = (uint64_t) stat_buf->st_dev;
+  insert_to_aux_cache (&id, flags, osversion, soname, 1);
+}
+
+/* Load auxiliary cache to search for unchanged entries.   */
+void
+load_aux_cache (const char *aux_cache_name)
+{
+  int fd = open (aux_cache_name, O_RDONLY);
+  if (fd < 0)
+    {
+      init_aux_cache ();
+      return;
+    }
+
+  struct stat64 st;
+  if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
+    {
+      close (fd);
+      init_aux_cache ();
+      return;
+    }
+
+  size_t aux_cache_size = st.st_size;
+  struct aux_cache_file *aux_cache
+    = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (aux_cache == MAP_FAILED
+      || aux_cache_size < sizeof (struct aux_cache_file)
+      || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
+      || aux_cache_size != (sizeof(struct aux_cache_file) +
+			    aux_cache->nlibs * sizeof(struct aux_cache_file_entry) +
+			    aux_cache->len_strings))
+    {
+      close (fd);
+      init_aux_cache ();
+      return;
+    }
+
+  aux_hash_size = nextprime (aux_cache->nlibs);
+  aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
+
+  const char *aux_cache_data
+    = (const char *) &aux_cache->libs[aux_cache->nlibs];
+  for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
+    insert_to_aux_cache (&aux_cache->libs[i].id,
+			 aux_cache->libs[i].flags,
+			 aux_cache->libs[i].osversion,
+			 aux_cache->libs[i].soname == 0
+			 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
+			 0);
+
+  munmap (aux_cache, aux_cache_size);
+  close (fd);
+}
+
+/* Save the contents of the auxiliary cache.  */
+void
+save_aux_cache (const char *aux_cache_name)
+{
+  /* Count the length of all sonames.  We start with empty string.  */
+  size_t total_strlen = 1;
+  /* Number of cache entries.  */
+  int cache_entry_count = 0;
+
+  for (size_t i = 0; i < aux_hash_size; ++i)
+    for (struct aux_cache_entry *entry = aux_hash[i];
+	 entry != NULL; entry = entry->next)
+      if (entry->used)
+	{
+	  ++cache_entry_count;
+	  if (entry->soname != NULL)
+	    total_strlen += strlen (entry->soname) + 1;
+	}
+
+  /* Auxiliary cache.  */
+  size_t file_entries_size
+    = sizeof (struct aux_cache_file)
+      + cache_entry_count * sizeof (struct aux_cache_file_entry);
+  struct aux_cache_file *file_entries
+    = xmalloc (file_entries_size + total_strlen);
+
+  /* Fill in the header of the auxiliary cache.  */
+  memset (file_entries, '\0', sizeof (struct aux_cache_file));
+  memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
+
+  file_entries->nlibs = cache_entry_count;
+  file_entries->len_strings = total_strlen;
+
+  /* Initial String offset for auxiliary cache is always after the
+     special empty string.  */
+  unsigned int str_offset = 1;
+
+  /* An array for all strings.  */
+  char *str = (char *) file_entries + file_entries_size;
+  *str++ = '\0';
+
+  size_t idx = 0;
+  for (size_t i = 0; i < aux_hash_size; ++i)
+    for (struct aux_cache_entry *entry = aux_hash[i];
+	 entry != NULL; entry = entry->next)
+      if (entry->used)
+	{
+	  file_entries->libs[idx].id = entry->id;
+	  file_entries->libs[idx].flags = entry->flags;
+	  if (entry->soname == NULL)
+	    file_entries->libs[idx].soname = 0;
+	  else
+	    {
+	      file_entries->libs[idx].soname = str_offset;
+
+	      size_t len = strlen (entry->soname) + 1;
+	      str = mempcpy (str, entry->soname, len);
+	      str_offset += len;
+	    }
+	  file_entries->libs[idx].osversion = entry->osversion;
+	  file_entries->libs[idx++].pad = 0;
+	}
+
+  /* Write out auxiliary cache file.  */
+  /* Write auxiliary cache first to a temporary file and rename it later.  */
+
+  char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
+  sprintf (temp_name, "%s~", aux_cache_name);
+
+  /* Check that directory exists and create if needed.  */
+  char *dir = strdupa (aux_cache_name);
+  dir = dirname (dir);
+
+  struct stat64 st;
+  if (stat64 (dir, &st) < 0)
+    {
+      if (mkdir (dir, 0700) < 0)
+	goto out_fail;
+    }
+
+  /* Create file.  */
+  int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
+		 S_IRUSR|S_IWUSR);
+  if (fd < 0)
+    goto out_fail;
+
+  if (write (fd, file_entries, file_entries_size + total_strlen)
+      != (ssize_t) (file_entries_size + total_strlen)
+      || close (fd))
+    {
+      unlink (temp_name);
+      goto out_fail;
+    }
+
+  /* Move temporary to its final location.  */
+  if (rename (temp_name, aux_cache_name))
+    unlink (temp_name);
+
+out_fail:
+  /* Free allocated memory.  */
+  free (temp_name);
+  free (file_entries);
+}
diff --git a/REORG.TODO/elf/chroot_canon.c b/REORG.TODO/elf/chroot_canon.c
new file mode 100644
index 0000000000..78cd6f4a5e
--- /dev/null
+++ b/REORG.TODO/elf/chroot_canon.c
@@ -0,0 +1,177 @@
+/* Return the canonical absolute name of a given file inside chroot.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <eloop-threshold.h>
+#include <ldconfig.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was
+   done first.  A canonical name does not contain any `.', `..' components
+   nor any repeated path separators ('/') or symlinks.  All path components
+   must exist and NAME must be absolute filename.  The result is malloc'd.
+   The returned name includes the CHROOT prefix.  */
+
+char *
+chroot_canon (const char *chroot, const char *name)
+{
+  char *rpath;
+  char *dest;
+  char *extra_buf = NULL;
+  char *rpath_root;
+  const char *start;
+  const char *end;
+  const char *rpath_limit;
+  int num_links = 0;
+  size_t chroot_len = strlen (chroot);
+
+  if (chroot_len < 1)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  rpath = xmalloc (chroot_len + PATH_MAX);
+
+  rpath_limit = rpath + chroot_len + PATH_MAX;
+
+  rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1;
+  if (*rpath_root != '/')
+    *++rpath_root = '/';
+  dest = rpath_root + 1;
+
+  for (start = end = name; *start; start = end)
+    {
+      struct stat64 st;
+
+      /* Skip sequence of multiple path-separators.  */
+      while (*start == '/')
+	++start;
+
+      /* Find end of path component.  */
+      for (end = start; *end && *end != '/'; ++end)
+	/* Nothing.  */;
+
+      if (end - start == 0)
+	break;
+      else if (end - start == 1 && start[0] == '.')
+	/* nothing */;
+      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+	{
+	  /* Back up to previous component, ignore if at root already.  */
+	  if (dest > rpath_root + 1)
+	    while ((--dest)[-1] != '/');
+	}
+      else
+	{
+	  size_t new_size;
+
+	  if (dest[-1] != '/')
+	    *dest++ = '/';
+
+	  if (dest + (end - start) >= rpath_limit)
+	    {
+	      ptrdiff_t dest_offset = dest - rpath;
+	      char *new_rpath;
+
+	      new_size = rpath_limit - rpath;
+	      if (end - start + 1 > PATH_MAX)
+		new_size += end - start + 1;
+	      else
+		new_size += PATH_MAX;
+	      new_rpath = (char *) xrealloc (rpath, new_size);
+	      rpath = new_rpath;
+	      rpath_limit = rpath + new_size;
+
+	      dest = rpath + dest_offset;
+	    }
+
+	  dest = mempcpy (dest, start, end - start);
+	  *dest = '\0';
+
+	  if (lstat64 (rpath, &st) < 0)
+	    {
+	      if (*end == '\0')
+		goto done;
+	      goto error;
+	    }
+
+	  if (S_ISLNK (st.st_mode))
+	    {
+	      char *buf = alloca (PATH_MAX);
+	      size_t len;
+
+	      if (++num_links > __eloop_threshold ())
+		{
+		  __set_errno (ELOOP);
+		  goto error;
+		}
+
+	      ssize_t n = readlink (rpath, buf, PATH_MAX - 1);
+	      if (n < 0)
+		{
+		  if (*end == '\0')
+		    goto done;
+		  goto error;
+		}
+	      buf[n] = '\0';
+
+	      if (!extra_buf)
+		extra_buf = alloca (PATH_MAX);
+
+	      len = strlen (end);
+	      if (len >= PATH_MAX - n)
+		{
+		  __set_errno (ENAMETOOLONG);
+		  goto error;
+		}
+
+	      /* Careful here, end may be a pointer into extra_buf... */
+	      memmove (&extra_buf[n], end, len + 1);
+	      name = end = memcpy (extra_buf, buf, n);
+
+	      if (buf[0] == '/')
+		dest = rpath_root + 1;	/* It's an absolute symlink */
+	      else
+		/* Back up to previous component, ignore if at root already: */
+		if (dest > rpath_root + 1)
+		  while ((--dest)[-1] != '/');
+	    }
+	}
+    }
+ done:
+  if (dest > rpath_root + 1 && dest[-1] == '/')
+    --dest;
+  *dest = '\0';
+
+  return rpath;
+
+ error:
+  free (rpath);
+  return NULL;
+}
diff --git a/REORG.TODO/elf/circleload1.c b/REORG.TODO/elf/circleload1.c
new file mode 100644
index 0000000000..990ff84a84
--- /dev/null
+++ b/REORG.TODO/elf/circleload1.c
@@ -0,0 +1,166 @@
+#include <dlfcn.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+static int
+check_loaded_objects (const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int errors = 0;
+
+  for (n = 0; loaded[n]; n++)
+    /* NOTHING */;
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = MAPS; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name[0])
+	printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded[n] != NULL; n++)
+	    {
+	      if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0)
+	        {
+		  found[n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (match == 0)
+	    {
+	      ++errors;
+	      printf ("ERRORS: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded[n] != NULL; n++)
+    {
+      if (found[n] == 0)
+        {
+	  ++errors;
+	  printf ("ERRORS: %s is not loaded\n", loaded[n]);
+	}
+    }
+
+  return errors;
+}
+
+static int
+load_dso (const char **loading, int undef, int flag)
+{
+  void *obj;
+  const char *loaded[] = { NULL, NULL, NULL, NULL };
+  int errors = 0;
+  const char *errstring;
+
+  printf ("\nThis is what is in memory now:\n");
+  errors += check_loaded_objects (loaded);
+
+  printf ("Loading shared object %s: %s\n", loading[0],
+	 flag == RTLD_LAZY ? "RTLD_LAZY" : "RTLD_NOW");
+  obj = dlopen (loading[0], flag);
+  if (obj == NULL)
+    {
+      if (flag == RTLD_LAZY)
+	{
+	  ++errors;
+	  printf ("ERRORS: dlopen shouldn't fail for RTLD_LAZY\n");
+	}
+
+      errstring = dlerror ();
+      if (strstr (errstring, "undefined symbol") == 0
+	  || strstr (errstring, "circlemod2_undefined") == 0)
+	{
+	  ++errors;
+	  printf ("ERRORS: dlopen: `%s': Invalid error string\n",
+		  errstring);
+	}
+      else
+	printf ("dlopen: %s\n", errstring);
+    }
+  else
+    {
+      if (undef && flag == RTLD_NOW)
+	{
+	  ++errors;
+	  printf ("ERRORS: dlopen shouldn't work for RTLD_NOW\n");
+	}
+
+      if (!undef)
+	{
+	  int (*func) (void);
+
+	  func = dlsym (obj, "circlemod1");
+	  if (func == NULL)
+	    {
+	      ++errors;
+	      printf ("ERRORS: cannot get address of \"circlemod1\": %s\n",
+		      dlerror ());
+	    }
+	  else if (func () != 3)
+	    {
+	      ++errors;
+	      printf ("ERRORS: function \"circlemod1\" returned wrong result\n");
+	    }
+	}
+
+      loaded[0] = loading[0];
+      loaded[1] = loading[1];
+      loaded[2] = loading[2];
+    }
+  errors += check_loaded_objects (loaded);
+
+  if (obj)
+    {
+      printf ("UnLoading shared object %s\n", loading[0]);
+      dlclose (obj);
+      loaded[0] = NULL;
+      loaded[1] = NULL;
+      loaded[2] = NULL;
+      errors += check_loaded_objects (loaded);
+    }
+
+  return errors;
+}
+
+int
+main (void)
+{
+  int errors = 0;
+  const char *loading[3];
+
+  loading[0] = "circlemod1a.so";
+  loading[1] = "circlemod2a.so";
+  loading[2] = "circlemod3a.so";
+  errors += load_dso (loading, 0, RTLD_LAZY);
+  errors += load_dso (loading, 0, RTLD_NOW);
+
+  loading[0] = "circlemod1.so";
+  loading[1] = "circlemod2.so";
+  loading[2] = "circlemod3.so";
+  errors += load_dso (loading, 1, RTLD_LAZY);
+  errors += load_dso (loading, 1, RTLD_NOW);
+
+  if (errors != 0)
+    printf ("%d errors found\n", errors);
+
+  return errors;
+}
diff --git a/REORG.TODO/elf/circlemod1.c b/REORG.TODO/elf/circlemod1.c
new file mode 100644
index 0000000000..933ccd3c02
--- /dev/null
+++ b/REORG.TODO/elf/circlemod1.c
@@ -0,0 +1,7 @@
+extern int circlemod2 (void);
+
+int
+circlemod1 (void)
+{
+  return circlemod2 ();
+}
diff --git a/REORG.TODO/elf/circlemod1a.c b/REORG.TODO/elf/circlemod1a.c
new file mode 100644
index 0000000000..45f229136d
--- /dev/null
+++ b/REORG.TODO/elf/circlemod1a.c
@@ -0,0 +1 @@
+#include "circlemod1.c"
diff --git a/REORG.TODO/elf/circlemod2.c b/REORG.TODO/elf/circlemod2.c
new file mode 100644
index 0000000000..ed8c1175fb
--- /dev/null
+++ b/REORG.TODO/elf/circlemod2.c
@@ -0,0 +1,9 @@
+extern void circlemod2_undefined (void);
+extern int circlemod3 (void);
+
+int
+circlemod2 (void)
+{
+  circlemod2_undefined ();
+  return circlemod3 ();
+}
diff --git a/REORG.TODO/elf/circlemod2a.c b/REORG.TODO/elf/circlemod2a.c
new file mode 100644
index 0000000000..dc6410b28b
--- /dev/null
+++ b/REORG.TODO/elf/circlemod2a.c
@@ -0,0 +1,7 @@
+extern int circlemod3 (void);
+
+int
+circlemod2 (void)
+{
+  return circlemod3 ();
+}
diff --git a/REORG.TODO/elf/circlemod3.c b/REORG.TODO/elf/circlemod3.c
new file mode 100644
index 0000000000..8d16fe682f
--- /dev/null
+++ b/REORG.TODO/elf/circlemod3.c
@@ -0,0 +1,14 @@
+extern int circlemod1 (void);
+extern int circlemod2 (void);
+
+int
+circlemod3 (void)
+{
+  return 3;
+}
+
+int
+circlemod3a (void)
+{
+  return circlemod1 () + circlemod2 ();
+}
diff --git a/REORG.TODO/elf/circlemod3a.c b/REORG.TODO/elf/circlemod3a.c
new file mode 100644
index 0000000000..f1b166ef84
--- /dev/null
+++ b/REORG.TODO/elf/circlemod3a.c
@@ -0,0 +1 @@
+#include "circlemod3.c"
diff --git a/REORG.TODO/elf/constload1.c b/REORG.TODO/elf/constload1.c
new file mode 100644
index 0000000000..7381beea88
--- /dev/null
+++ b/REORG.TODO/elf/constload1.c
@@ -0,0 +1,32 @@
+#include <dlfcn.h>
+#include <errno.h>
+#include <error.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int (*foo) (void);
+  void *h;
+  int ret;
+
+  mtrace ();
+
+  h = dlopen ("constload2.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h == NULL)
+    error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\"");
+  foo = dlsym (h, "foo");
+  ret = foo ();
+  /* Note that the following dlclose() call cannot unload the objects.
+     Due to the introduced relocation dependency constload2.so depends
+     on constload3.so and the dependencies of constload2.so on constload3.so
+     is not visible to ld.so since it's done using dlopen().  */
+  if (dlclose (h) != 0)
+    {
+      puts ("failed to close");
+      exit (EXIT_FAILURE);
+    }
+  return ret;
+}
diff --git a/REORG.TODO/elf/constload2.c b/REORG.TODO/elf/constload2.c
new file mode 100644
index 0000000000..bf1bf182f3
--- /dev/null
+++ b/REORG.TODO/elf/constload2.c
@@ -0,0 +1,50 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int bar (void);
+extern int baz (void);
+extern int foo (void);
+extern void __attribute__ ((__constructor__)) init (void);
+
+void *h;
+
+int
+foo (void)
+{
+  return 42 + bar ();
+}
+
+int
+baz (void)
+{
+  return -21;
+}
+
+
+void
+__attribute__ ((__constructor__))
+init (void)
+{
+  h = dlopen ("constload3.so", RTLD_GLOBAL | RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("failed to load constload3");
+      exit (1);
+    }
+  else
+    puts ("succeeded loading constload3");
+}
+
+static void
+__attribute__ ((__destructor__))
+fini (void)
+{
+  if (dlclose (h) != 0)
+    {
+      puts ("failed to unload constload3");
+      exit (1);
+    }
+  else
+    puts ("succeeded unloading constload3");
+}
diff --git a/REORG.TODO/elf/constload3.c b/REORG.TODO/elf/constload3.c
new file mode 100644
index 0000000000..9c37620bba
--- /dev/null
+++ b/REORG.TODO/elf/constload3.c
@@ -0,0 +1,8 @@
+extern int baz (void);
+extern int bar (void);
+
+int
+bar (void)
+{
+  return -21 + baz ();
+}
diff --git a/REORG.TODO/elf/dblload.c b/REORG.TODO/elf/dblload.c
new file mode 100644
index 0000000000..52389a60ce
--- /dev/null
+++ b/REORG.TODO/elf/dblload.c
@@ -0,0 +1,53 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int
+main (void)
+{
+  void *p1;
+  void *p2;
+  int (*fp) (void);
+  int result;
+
+  mtrace ();
+
+  p1 = dlopen ("dblloadmod1.so", RTLD_LAZY);
+  if (p1 == NULL)
+    {
+      printf ("cannot open dblloadmod1.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  p2 = dlopen ("dblloadmod2.so", RTLD_LAZY);
+  if (p1 == NULL)
+    {
+      printf ("cannot open dblloadmod2.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  fp = dlsym (p1, "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get function \"foo\": %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  result = fp ();
+
+  if (dlclose (p1) != 0)
+    {
+      printf ("error while closing dblloadmod1.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  if (dlclose (p2) != 0)
+    {
+      printf ("error while closing dblloadmod2.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  return result;
+}
diff --git a/REORG.TODO/elf/dblloadmod1.c b/REORG.TODO/elf/dblloadmod1.c
new file mode 100644
index 0000000000..ecec29ec63
--- /dev/null
+++ b/REORG.TODO/elf/dblloadmod1.c
@@ -0,0 +1,8 @@
+extern int bar (void);
+extern int foo (void);
+
+int
+foo (void)
+{
+  return 10 + bar ();
+}
diff --git a/REORG.TODO/elf/dblloadmod2.c b/REORG.TODO/elf/dblloadmod2.c
new file mode 100644
index 0000000000..3e20aa941b
--- /dev/null
+++ b/REORG.TODO/elf/dblloadmod2.c
@@ -0,0 +1,15 @@
+extern int bar (void);
+extern int baz (void);
+extern int xyzzy (void);
+
+int
+baz (void)
+{
+  return -42;
+}
+
+int
+xyzzy (void)
+{
+  return 10 + bar ();
+}
diff --git a/REORG.TODO/elf/dblloadmod3.c b/REORG.TODO/elf/dblloadmod3.c
new file mode 100644
index 0000000000..80ac3a6375
--- /dev/null
+++ b/REORG.TODO/elf/dblloadmod3.c
@@ -0,0 +1,8 @@
+extern int bar (void);
+extern int baz (void);
+
+int
+bar (void)
+{
+  return 32 + baz ();
+}
diff --git a/REORG.TODO/elf/dblunload.c b/REORG.TODO/elf/dblunload.c
new file mode 100644
index 0000000000..ab0b2a5e9e
--- /dev/null
+++ b/REORG.TODO/elf/dblunload.c
@@ -0,0 +1,53 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int
+main (void)
+{
+  void *p1;
+  void *p2;
+  int (*fp) (void);
+  int result;
+
+  mtrace ();
+
+  p1 = dlopen ("dblloadmod1.so", RTLD_LAZY);
+  if (p1 == NULL)
+    {
+      printf ("cannot load dblloadmod1.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  p2 = dlopen ("dblloadmod2.so", RTLD_LAZY);
+  if (p2 == NULL)
+    {
+      printf ("cannot load dblloadmod2.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  if (dlclose (p1) != 0)
+    {
+      printf ("error while closing dblloadmod1.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  fp = dlsym (p2, "xyzzy");
+  if (fp == NULL)
+    {
+      printf ("cannot get function \"xyzzy\": %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  result = fp ();
+
+  if (dlclose (p2) != 0)
+    {
+      printf ("error while closing dblloadmod2.so: %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  return result;
+}
diff --git a/REORG.TODO/elf/dep1.c b/REORG.TODO/elf/dep1.c
new file mode 100644
index 0000000000..7ef47adb43
--- /dev/null
+++ b/REORG.TODO/elf/dep1.c
@@ -0,0 +1,25 @@
+#include <unistd.h>
+
+extern int dep1 (void);
+extern int dep2 (void);
+extern int dep4 (void);
+
+static void
+__attribute__ ((constructor))
+init (void)
+{
+  write (1, "3", 1);
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  write (1, "6", 1);
+}
+
+int
+dep1 (void)
+{
+  return dep4 () - dep2 ();
+}
diff --git a/REORG.TODO/elf/dep2.c b/REORG.TODO/elf/dep2.c
new file mode 100644
index 0000000000..749036a4ec
--- /dev/null
+++ b/REORG.TODO/elf/dep2.c
@@ -0,0 +1,25 @@
+#include <unistd.h>
+
+extern int dep2 (void);
+extern int dep3 (void);
+extern int dep4 (void);
+
+static void
+__attribute__ ((constructor))
+init (void)
+{
+  write (1, "2", 1);
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  write (1, "7", 1);
+}
+
+int
+dep2 (void)
+{
+  return dep3 () - dep4 ();
+}
diff --git a/REORG.TODO/elf/dep3.c b/REORG.TODO/elf/dep3.c
new file mode 100644
index 0000000000..3df6282009
--- /dev/null
+++ b/REORG.TODO/elf/dep3.c
@@ -0,0 +1,23 @@
+#include <unistd.h>
+
+extern int dep3 (void);
+
+static void
+__attribute__ ((constructor))
+init (void)
+{
+  write (1, "0", 1);
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  write (1, "9\n", 2);
+}
+
+int
+dep3 (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/dep4.c b/REORG.TODO/elf/dep4.c
new file mode 100644
index 0000000000..c496d6f531
--- /dev/null
+++ b/REORG.TODO/elf/dep4.c
@@ -0,0 +1,24 @@
+#include <unistd.h>
+
+extern int dep3 (void);
+extern int dep4 (void);
+
+static void
+__attribute__ ((constructor))
+init (void)
+{
+  write (1, "1", 1);
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  write (1, "8", 1);
+}
+
+int
+dep4 (void)
+{
+  return dep3 ();
+}
diff --git a/REORG.TODO/elf/dl-addr-obj.c b/REORG.TODO/elf/dl-addr-obj.c
new file mode 100644
index 0000000000..62aa630ce5
--- /dev/null
+++ b/REORG.TODO/elf/dl-addr-obj.c
@@ -0,0 +1,75 @@
+/* Determine if address is inside object load segments.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <elf.h>
+
+/* Return non-zero if ADDR lies within one of L's loadable segments.
+   We have three cases we care about.
+
+   Case 1: addr is above a segment.
+   +==================+<- l_map_end
+   |                  |<- addr
+   |------------------|<- l_addr + p_vaddr + p_memsz
+   |                  |
+   |                  |
+   |------------------|<- l_addr + p_vaddr
+   |------------------|<- l_addr
+   |                  |
+   +==================+<- l_map_start
+
+   Case 2: addr is within a segments.
+   +==================+<- l_map_end
+   |                  |
+   |------------------|<- l_addr + p_vaddr + p_memsz
+   |                  |<- addr
+   |                  |
+   |------------------|<- l_addr + p_vaddr
+   |------------------|<- l_addr
+   |                  |
+   +==================+<- l_map_start
+
+   Case 3: addr is below a segments.
+   +==================+<- l_map_end
+   |                  |
+   |------------------|<- l_addr + p_vaddr + p_memsz
+   |                  |
+   |                  |
+   |------------------|<- l_addr + p_vaddr
+   |------------------|<- l_addr
+   |                  |<- addr
+   +==================+<- l_map_start
+
+   All the arithmetic is unsigned and we shift all the values down by
+   l_addr + p_vaddr and then compare the normalized addr to the range
+   of interest i.e. 0 <= addr < p_memsz.
+
+*/
+int
+internal_function
+_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
+{
+  int n = l->l_phnum;
+  const ElfW(Addr) reladdr = addr - l->l_addr;
+
+  while (--n >= 0)
+    if (l->l_phdr[n].p_type == PT_LOAD
+	&& reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
+      return 1;
+  return 0;
+}
diff --git a/REORG.TODO/elf/dl-addr.c b/REORG.TODO/elf/dl-addr.c
new file mode 100644
index 0000000000..1fac63d1a9
--- /dev/null
+++ b/REORG.TODO/elf/dl-addr.c
@@ -0,0 +1,146 @@
+/* Locate the shared object symbol nearest a given address.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <ldsodefs.h>
+
+
+static inline void
+__attribute ((always_inline))
+determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
+		struct link_map **mapp, const ElfW(Sym) **symbolp)
+{
+  /* Now we know what object the address lies in.  */
+  info->dli_fname = match->l_name;
+  info->dli_fbase = (void *) match->l_map_start;
+
+  /* If this is the main program the information is incomplete.  */
+  if (__builtin_expect (match->l_name[0], 'a') == '\0'
+      && match->l_type == lt_executable)
+    info->dli_fname = _dl_argv[0];
+
+  const ElfW(Sym) *symtab
+    = (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
+  const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
+
+  ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
+
+  const ElfW(Sym) *matchsym = NULL;
+  if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
+		    + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
+    {
+      /* We look at all symbol table entries referenced by the hash
+	 table.  */
+      for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
+	{
+	  Elf32_Word symndx = match->l_gnu_buckets[bucket];
+	  if (symndx != 0)
+	    {
+	      const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
+
+	      do
+		{
+		  /* The hash table never references local symbols so
+		     we can omit that test here.  */
+		  if ((symtab[symndx].st_shndx != SHN_UNDEF
+		       || symtab[symndx].st_value != 0)
+		      && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
+		      && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
+					    matchsym, addr)
+		      && symtab[symndx].st_name < strtabsize)
+		    matchsym = (ElfW(Sym) *) &symtab[symndx];
+
+		  ++symndx;
+		}
+	      while ((*hasharr++ & 1u) == 0);
+	    }
+	}
+    }
+  else
+    {
+      const ElfW(Sym) *symtabend;
+      if (match->l_info[DT_HASH] != NULL)
+	symtabend = (symtab
+		     + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
+      else
+	/* There is no direct way to determine the number of symbols in the
+	   dynamic symbol table and no hash table is present.  The ELF
+	   binary is ill-formed but what shall we do?  Use the beginning of
+	   the string table which generally follows the symbol table.  */
+	symtabend = (const ElfW(Sym) *) strtab;
+
+      for (; (void *) symtab < (void *) symtabend; ++symtab)
+	if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+	     || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
+	    && __glibc_likely (!dl_symbol_visibility_binds_local_p (symtab))
+	    && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
+	    && (symtab->st_shndx != SHN_UNDEF
+		|| symtab->st_value != 0)
+	    && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
+	    && symtab->st_name < strtabsize)
+	  matchsym = (ElfW(Sym) *) symtab;
+    }
+
+  if (mapp)
+    *mapp = match;
+  if (symbolp)
+    *symbolp = matchsym;
+
+  if (matchsym)
+    {
+      /* We found a symbol close by.  Fill in its name and exact
+	 address.  */
+      lookup_t matchl = LOOKUP_VALUE (match);
+
+      info->dli_sname = strtab + matchsym->st_name;
+      info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
+    }
+  else
+    {
+      /* No symbol matches.  We return only the containing object.  */
+      info->dli_sname = NULL;
+      info->dli_saddr = NULL;
+    }
+}
+
+
+int
+internal_function
+_dl_addr (const void *address, Dl_info *info,
+	  struct link_map **mapp, const ElfW(Sym) **symbolp)
+{
+  const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
+  int result = 0;
+
+  /* Protect against concurrent loads and unloads.  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  struct link_map *l = _dl_find_dso_for_object (addr);
+
+  if (l)
+    {
+      determine_info (addr, l, info, mapp, symbolp);
+      result = 1;
+    }
+
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+  return result;
+}
+libc_hidden_def (_dl_addr)
diff --git a/REORG.TODO/elf/dl-brk.c b/REORG.TODO/elf/dl-brk.c
new file mode 100644
index 0000000000..c37cdfec33
--- /dev/null
+++ b/REORG.TODO/elf/dl-brk.c
@@ -0,0 +1,5 @@
+/* We can use the normal code but we also know the __curbrk is not exported
+   from ld.so.  */
+extern void *__curbrk attribute_hidden;
+
+#include <brk.c>
diff --git a/REORG.TODO/elf/dl-cache.c b/REORG.TODO/elf/dl-cache.c
new file mode 100644
index 0000000000..e9632da0b3
--- /dev/null
+++ b/REORG.TODO/elf/dl-cache.c
@@ -0,0 +1,325 @@
+/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <sys/mman.h>
+#include <dl-cache.h>
+#include <dl-procinfo.h>
+#include <stdint.h>
+#include <_itoa.h>
+#include <dl-hwcaps.h>
+
+#ifndef _DL_PLATFORMS_COUNT
+# define _DL_PLATFORMS_COUNT 0
+#endif
+
+/* This is the starting address and the size of the mmap()ed file.  */
+static struct cache_file *cache;
+static struct cache_file_new *cache_new;
+static size_t cachesize;
+
+/* 1 if cache_data + PTR points into the cache.  */
+#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
+
+#define SEARCH_CACHE(cache) \
+/* We use binary search since the table is sorted in the cache file.	      \
+   The first matching entry in the table is returned.			      \
+   It is important to use the same algorithm as used while generating	      \
+   the cache file.  */							      \
+do									      \
+  {									      \
+    left = 0;								      \
+    right = cache->nlibs - 1;						      \
+									      \
+    while (left <= right)						      \
+      {									      \
+	__typeof__ (cache->libs[0].key) key;				      \
+									      \
+	middle = (left + right) / 2;					      \
+									      \
+	key = cache->libs[middle].key;					      \
+									      \
+	/* Make sure string table indices are not bogus before using	      \
+	   them.  */							      \
+	if (! _dl_cache_verify_ptr (key))				      \
+	  {								      \
+	    cmpres = 1;							      \
+	    break;							      \
+	  }								      \
+									      \
+	/* Actually compare the entry with the key.  */			      \
+	cmpres = _dl_cache_libcmp (name, cache_data + key);		      \
+	if (__glibc_unlikely (cmpres == 0))				      \
+	  {								      \
+	    /* Found it.  LEFT now marks the last entry for which we	      \
+	       know the name is correct.  */				      \
+	    left = middle;						      \
+									      \
+	    /* There might be entries with this name before the one we	      \
+	       found.  So we have to find the beginning.  */		      \
+	    while (middle > 0)						      \
+	      {								      \
+		__typeof__ (cache->libs[0].key) key;			      \
+									      \
+		key = cache->libs[middle - 1].key;			      \
+		/* Make sure string table indices are not bogus before	      \
+		   using them.  */					      \
+		if (! _dl_cache_verify_ptr (key)			      \
+		    /* Actually compare the entry.  */			      \
+		    || _dl_cache_libcmp (name, cache_data + key) != 0)	      \
+		  break;						      \
+		--middle;						      \
+	      }								      \
+									      \
+	    do								      \
+	      {								      \
+		int flags;						      \
+		__typeof__ (cache->libs[0]) *lib = &cache->libs[middle];      \
+									      \
+		/* Only perform the name test if necessary.  */		      \
+		if (middle > left					      \
+		    /* We haven't seen this string so far.  Test whether the  \
+		       index is ok and whether the name matches.  Otherwise   \
+		       we are done.  */					      \
+		    && (! _dl_cache_verify_ptr (lib->key)		      \
+			|| (_dl_cache_libcmp (name, cache_data + lib->key)    \
+			    != 0)))					      \
+		  break;						      \
+									      \
+		flags = lib->flags;					      \
+		if (_dl_cache_check_flags (flags)			      \
+		    && _dl_cache_verify_ptr (lib->value))		      \
+		  {							      \
+		    if (best == NULL || flags == GLRO(dl_correct_cache_id))   \
+		      {							      \
+			HWCAP_CHECK;					      \
+			best = cache_data + lib->value;			      \
+									      \
+			if (flags == GLRO(dl_correct_cache_id))		      \
+			  /* We've found an exact match for the shared	      \
+			     object and no general `ELF' release.  Stop	      \
+			     searching.  */				      \
+			  break;					      \
+		      }							      \
+		  }							      \
+	      }								      \
+	    while (++middle <= right);					      \
+	    break;							      \
+	}								      \
+									      \
+	if (cmpres < 0)							      \
+	  left = middle + 1;						      \
+	else								      \
+	  right = middle - 1;						      \
+      }									      \
+  }									      \
+while (0)
+
+
+int
+internal_function
+_dl_cache_libcmp (const char *p1, const char *p2)
+{
+  while (*p1 != '\0')
+    {
+      if (*p1 >= '0' && *p1 <= '9')
+        {
+          if (*p2 >= '0' && *p2 <= '9')
+            {
+	      /* Must compare this numerically.  */
+	      int val1;
+	      int val2;
+
+	      val1 = *p1++ - '0';
+	      val2 = *p2++ - '0';
+	      while (*p1 >= '0' && *p1 <= '9')
+	        val1 = val1 * 10 + *p1++ - '0';
+	      while (*p2 >= '0' && *p2 <= '9')
+	        val2 = val2 * 10 + *p2++ - '0';
+	      if (val1 != val2)
+		return val1 - val2;
+	    }
+	  else
+            return 1;
+        }
+      else if (*p2 >= '0' && *p2 <= '9')
+        return -1;
+      else if (*p1 != *p2)
+        return *p1 - *p2;
+      else
+	{
+	  ++p1;
+	  ++p2;
+	}
+    }
+  return *p1 - *p2;
+}
+
+
+/* Look up NAME in ld.so.cache and return the file name stored there, or null
+   if none is found.  The cache is loaded if it was not already.  If loading
+   the cache previously failed there will be no more attempts to load it.
+   The caller is responsible for freeing the returned string.  The ld.so.cache
+   may be unmapped at any time by a completing recursive dlopen and
+   this function must take care that it does not return references to
+   any data in the mapping.  */
+char *
+internal_function
+_dl_load_cache_lookup (const char *name)
+{
+  int left, right, middle;
+  int cmpres;
+  const char *cache_data;
+  uint32_t cache_data_size;
+  const char *best;
+
+  /* Print a message if the loading of libs is traced.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+    _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
+
+  if (cache == NULL)
+    {
+      /* Read the contents of the file.  */
+      void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
+					       PROT_READ);
+
+      /* We can handle three different cache file formats here:
+	 - the old libc5/glibc2.0/2.1 format
+	 - the old format with the new format in it
+	 - only the new format
+	 The following checks if the cache contains any of these formats.  */
+      if (file != MAP_FAILED && cachesize > sizeof *cache
+	  && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
+	{
+	  size_t offset;
+	  /* Looks ok.  */
+	  cache = file;
+
+	  /* Check for new version.  */
+	  offset = ALIGN_CACHE (sizeof (struct cache_file)
+				+ cache->nlibs * sizeof (struct file_entry));
+
+	  cache_new = (struct cache_file_new *) ((void *) cache + offset);
+	  if (cachesize < (offset + sizeof (struct cache_file_new))
+	      || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
+			 sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
+	    cache_new = (void *) -1;
+	}
+      else if (file != MAP_FAILED && cachesize > sizeof *cache_new
+	       && memcmp (file, CACHEMAGIC_VERSION_NEW,
+			  sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
+	{
+	  cache_new = file;
+	  cache = file;
+	}
+      else
+	{
+	  if (file != MAP_FAILED)
+	    __munmap (file, cachesize);
+	  cache = (void *) -1;
+	}
+
+      assert (cache != NULL);
+    }
+
+  if (cache == (void *) -1)
+    /* Previously looked for the cache file and didn't find it.  */
+    return NULL;
+
+  best = NULL;
+
+  if (cache_new != (void *) -1)
+    {
+      uint64_t platform;
+
+      /* This is where the strings start.  */
+      cache_data = (const char *) cache_new;
+
+      /* Now we can compute how large the string table is.  */
+      cache_data_size = (const char *) cache + cachesize - cache_data;
+
+      platform = _dl_string_platform (GLRO(dl_platform));
+      if (platform != (uint64_t) -1)
+	platform = 1ULL << platform;
+
+      uint64_t hwcap_mask = GET_HWCAP_MASK();
+
+#define _DL_HWCAP_TLS_MASK (1LL << 63)
+      uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & hwcap_mask)
+				 | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
+
+      /* Only accept hwcap if it's for the right platform.  */
+#define HWCAP_CHECK \
+      if (lib->hwcap & hwcap_exclude)					      \
+	continue;							      \
+      if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion))	      \
+	continue;							      \
+      if (_DL_PLATFORMS_COUNT						      \
+	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0			      \
+	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform)		      \
+	continue
+      SEARCH_CACHE (cache_new);
+    }
+  else
+    {
+      /* This is where the strings start.  */
+      cache_data = (const char *) &cache->libs[cache->nlibs];
+
+      /* Now we can compute how large the string table is.  */
+      cache_data_size = (const char *) cache + cachesize - cache_data;
+
+#undef HWCAP_CHECK
+#define HWCAP_CHECK do {} while (0)
+      SEARCH_CACHE (cache);
+    }
+
+  /* Print our result if wanted.  */
+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)
+      && best != NULL)
+    _dl_debug_printf ("  trying file=%s\n", best);
+
+  if (best == NULL)
+    return NULL;
+
+  /* The double copy is *required* since malloc may be interposed
+     and call dlopen itself whose completion would unmap the data
+     we are accessing. Therefore we must make the copy of the
+     mapping data without using malloc.  */
+  char *temp;
+  temp = alloca (strlen (best) + 1);
+  strcpy (temp, best);
+  return __strdup (temp);
+}
+
+#ifndef MAP_COPY
+/* If the system does not support MAP_COPY we cannot leave the file open
+   all the time since this would create problems when the file is replaced.
+   Therefore we provide this function to close the file and open it again
+   once needed.  */
+void
+_dl_unload_cache (void)
+{
+  if (cache != NULL && cache != (struct cache_file *) -1)
+    {
+      __munmap (cache, cachesize);
+      cache = NULL;
+    }
+}
+#endif
diff --git a/REORG.TODO/elf/dl-caller.c b/REORG.TODO/elf/dl-caller.c
new file mode 100644
index 0000000000..b4c5335baa
--- /dev/null
+++ b/REORG.TODO/elf/dl-caller.c
@@ -0,0 +1,86 @@
+/* Check whether caller comes from the right place.
+   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <ldsodefs.h>
+#include <stddef.h>
+#include <caller.h>
+#include <gnu/lib-names.h>
+
+
+int
+attribute_hidden
+_dl_check_caller (const void *caller, enum allowmask mask)
+{
+  static const char expected1[] = LIBC_SO;
+  static const char expected2[] = LIBDL_SO;
+#ifdef LIBPTHREAD_SO
+  static const char expected3[] = LIBPTHREAD_SO;
+#endif
+  static const char expected4[] = LD_SO;
+
+  for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
+    for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
+	 l = l->l_next)
+      if (caller >= (const void *) l->l_map_start
+	  && caller < (const void *) l->l_text_end)
+	{
+	  /* The address falls into this DSO's address range.  Check the
+	     name.  */
+	  if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0)
+	    return 0;
+	  if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0)
+	    return 0;
+#ifdef LIBPTHREAD_SO
+	  if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0)
+	    return 0;
+#endif
+	  if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0)
+	    return 0;
+
+	  struct libname_list *runp = l->l_libname;
+
+	  while (runp != NULL)
+	    {
+	      if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0)
+		return 0;
+	      if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0)
+		return 0;
+#ifdef LIBPTHREAD_SO
+	      if ((mask & allow_libpthread)
+		  && strcmp (expected3, runp->name) == 0)
+		return 0;
+#endif
+	      if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0)
+		return 0;
+
+	      runp = runp->next;
+	    }
+
+	  break;
+	}
+
+  /* Maybe the dynamic linker is not yet on the list.  */
+  if ((mask & allow_ldso) != 0
+      && caller >= (const void *) GL(dl_rtld_map).l_map_start
+      && caller < (const void *) GL(dl_rtld_map).l_text_end)
+    return 0;
+
+  /* No valid caller.  */
+  return 1;
+}
diff --git a/REORG.TODO/elf/dl-close.c b/REORG.TODO/elf/dl-close.c
new file mode 100644
index 0000000000..2b46b7cf8b
--- /dev/null
+++ b/REORG.TODO/elf/dl-close.c
@@ -0,0 +1,843 @@
+/* Close a shared object opened by `_dl_open'.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <libintl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libc-lock.h>
+#include <ldsodefs.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sysdep-cancel.h>
+#include <tls.h>
+#include <stap-probe.h>
+
+#include <dl-unmap-segments.h>
+
+
+/* Type of the constructor functions.  */
+typedef void (*fini_t) (void);
+
+
+/* Special l_idx value used to indicate which objects remain loaded.  */
+#define IDX_STILL_USED -1
+
+
+/* Returns true we an non-empty was found.  */
+static bool
+remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
+		 bool should_be_there)
+{
+  if (idx - disp >= listp->len)
+    {
+      if (listp->next == NULL)
+	{
+	  /* The index is not actually valid in the slotinfo list,
+	     because this object was closed before it was fully set
+	     up due to some error.  */
+	  assert (! should_be_there);
+	}
+      else
+	{
+	  if (remove_slotinfo (idx, listp->next, disp + listp->len,
+			       should_be_there))
+	    return true;
+
+	  /* No non-empty entry.  Search from the end of this element's
+	     slotinfo array.  */
+	  idx = disp + listp->len;
+	}
+    }
+  else
+    {
+      struct link_map *old_map = listp->slotinfo[idx - disp].map;
+
+      /* The entry might still be in its unused state if we are closing an
+	 object that wasn't fully set up.  */
+      if (__glibc_likely (old_map != NULL))
+	{
+	  assert (old_map->l_tls_modid == idx);
+
+	  /* Mark the entry as unused. */
+	  listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
+	  listp->slotinfo[idx - disp].map = NULL;
+	}
+
+      /* If this is not the last currently used entry no need to look
+	 further.  */
+      if (idx != GL(dl_tls_max_dtv_idx))
+	return true;
+    }
+
+  while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
+    {
+      --idx;
+
+      if (listp->slotinfo[idx - disp].map != NULL)
+	{
+	  /* Found a new last used index.  */
+	  GL(dl_tls_max_dtv_idx) = idx;
+	  return true;
+	}
+    }
+
+  /* No non-entry in this list element.  */
+  return false;
+}
+
+
+void
+_dl_close_worker (struct link_map *map, bool force)
+{
+  /* One less direct use.  */
+  --map->l_direct_opencount;
+
+  /* If _dl_close is called recursively (some destructor call dlclose),
+     just record that the parent _dl_close will need to do garbage collection
+     again and return.  */
+  static enum { not_pending, pending, rerun } dl_close_state;
+
+  if (map->l_direct_opencount > 0 || map->l_type != lt_loaded
+      || dl_close_state != not_pending)
+    {
+      if (map->l_direct_opencount == 0 && map->l_type == lt_loaded)
+	dl_close_state = rerun;
+
+      /* There are still references to this object.  Do nothing more.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+	_dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n",
+			  map->l_name, map->l_direct_opencount);
+
+      return;
+    }
+
+  Lmid_t nsid = map->l_ns;
+  struct link_namespaces *ns = &GL(dl_ns)[nsid];
+
+ retry:
+  dl_close_state = pending;
+
+  bool any_tls = false;
+  const unsigned int nloaded = ns->_ns_nloaded;
+  char used[nloaded];
+  char done[nloaded];
+  struct link_map *maps[nloaded];
+
+  /* Clear DF_1_NODELETE to force object deletion.  We don't need to touch
+     l_tls_dtor_count because forced object deletion only happens when an
+     error occurs during object load.  Destructor registration for TLS
+     non-POD objects should not have happened till then for this
+     object.  */
+  if (force)
+    map->l_flags_1 &= ~DF_1_NODELETE;
+
+  /* Run over the list and assign indexes to the link maps and enter
+     them into the MAPS array.  */
+  int idx = 0;
+  for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next)
+    {
+      l->l_idx = idx;
+      maps[idx] = l;
+      ++idx;
+
+    }
+  assert (idx == nloaded);
+
+  /* Prepare the bitmaps.  */
+  memset (used, '\0', sizeof (used));
+  memset (done, '\0', sizeof (done));
+
+  /* Keep track of the lowest index link map we have covered already.  */
+  int done_index = -1;
+  while (++done_index < nloaded)
+    {
+      struct link_map *l = maps[done_index];
+
+      if (done[done_index])
+	/* Already handled.  */
+	continue;
+
+      /* Check whether this object is still used.  */
+      if (l->l_type == lt_loaded
+	  && l->l_direct_opencount == 0
+	  && (l->l_flags_1 & DF_1_NODELETE) == 0
+	  /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
+	     acquire is sufficient and correct.  */
+	  && atomic_load_acquire (&l->l_tls_dtor_count) == 0
+	  && !used[done_index])
+	continue;
+
+      /* We need this object and we handle it now.  */
+      done[done_index] = 1;
+      used[done_index] = 1;
+      /* Signal the object is still needed.  */
+      l->l_idx = IDX_STILL_USED;
+
+      /* Mark all dependencies as used.  */
+      if (l->l_initfini != NULL)
+	{
+	  /* We are always the zeroth entry, and since we don't include
+	     ourselves in the dependency analysis start at 1.  */
+	  struct link_map **lp = &l->l_initfini[1];
+	  while (*lp != NULL)
+	    {
+	      if ((*lp)->l_idx != IDX_STILL_USED)
+		{
+		  assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
+
+		  if (!used[(*lp)->l_idx])
+		    {
+		      used[(*lp)->l_idx] = 1;
+		      /* If we marked a new object as used, and we've
+			 already processed it, then we need to go back
+			 and process again from that point forward to
+			 ensure we keep all of its dependencies also.  */
+		      if ((*lp)->l_idx - 1 < done_index)
+			done_index = (*lp)->l_idx - 1;
+		    }
+		}
+
+	      ++lp;
+	    }
+	}
+      /* And the same for relocation dependencies.  */
+      if (l->l_reldeps != NULL)
+	for (unsigned int j = 0; j < l->l_reldeps->act; ++j)
+	  {
+	    struct link_map *jmap = l->l_reldeps->list[j];
+
+	    if (jmap->l_idx != IDX_STILL_USED)
+	      {
+		assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
+
+		if (!used[jmap->l_idx])
+		  {
+		    used[jmap->l_idx] = 1;
+		    if (jmap->l_idx - 1 < done_index)
+		      done_index = jmap->l_idx - 1;
+		  }
+	      }
+	  }
+    }
+
+  /* Sort the entries.  */
+  _dl_sort_fini (maps, nloaded, used, nsid);
+
+  /* Call all termination functions at once.  */
+#ifdef SHARED
+  bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
+#endif
+  bool unload_any = false;
+  bool scope_mem_left = false;
+  unsigned int unload_global = 0;
+  unsigned int first_loaded = ~0;
+  for (unsigned int i = 0; i < nloaded; ++i)
+    {
+      struct link_map *imap = maps[i];
+
+      /* All elements must be in the same namespace.  */
+      assert (imap->l_ns == nsid);
+
+      if (!used[i])
+	{
+	  assert (imap->l_type == lt_loaded
+		  && (imap->l_flags_1 & DF_1_NODELETE) == 0);
+
+	  /* Call its termination function.  Do not do it for
+	     half-cooked objects.  */
+	  if (imap->l_init_called)
+	    {
+	      /* When debugging print a message first.  */
+	      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
+				    0))
+		_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+				  imap->l_name, nsid);
+
+	      if (imap->l_info[DT_FINI_ARRAY] != NULL)
+		{
+		  ElfW(Addr) *array =
+		    (ElfW(Addr) *) (imap->l_addr
+				    + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
+		  unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
+				     / sizeof (ElfW(Addr)));
+
+		  while (sz-- > 0)
+		    ((fini_t) array[sz]) ();
+		}
+
+	      /* Next try the old-style destructor.  */
+	      if (imap->l_info[DT_FINI] != NULL)
+		DL_CALL_DT_FINI (imap, ((void *) imap->l_addr
+			 + imap->l_info[DT_FINI]->d_un.d_ptr));
+	    }
+
+#ifdef SHARED
+	  /* Auditing checkpoint: we remove an object.  */
+	  if (__glibc_unlikely (do_audit))
+	    {
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  if (afct->objclose != NULL)
+		    /* Return value is ignored.  */
+		    (void) afct->objclose (&imap->l_audit[cnt].cookie);
+
+		  afct = afct->next;
+		}
+	    }
+#endif
+
+	  /* This object must not be used anymore.  */
+	  imap->l_removed = 1;
+
+	  /* We indeed have an object to remove.  */
+	  unload_any = true;
+
+	  if (imap->l_global)
+	    ++unload_global;
+
+	  /* Remember where the first dynamically loaded object is.  */
+	  if (i < first_loaded)
+	    first_loaded = i;
+	}
+      /* Else used[i].  */
+      else if (imap->l_type == lt_loaded)
+	{
+	  struct r_scope_elem *new_list = NULL;
+
+	  if (imap->l_searchlist.r_list == NULL && imap->l_initfini != NULL)
+	    {
+	      /* The object is still used.  But one of the objects we are
+		 unloading right now is responsible for loading it.  If
+		 the current object does not have it's own scope yet we
+		 have to create one.  This has to be done before running
+		 the finalizers.
+
+		 To do this count the number of dependencies.  */
+	      unsigned int cnt;
+	      for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt)
+		;
+
+	      /* We simply reuse the l_initfini list.  */
+	      imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1];
+	      imap->l_searchlist.r_nlist = cnt;
+
+	      new_list = &imap->l_searchlist;
+	    }
+
+	  /* Count the number of scopes which remain after the unload.
+	     When we add the local search list count it.  Always add
+	     one for the terminating NULL pointer.  */
+	  size_t remain = (new_list != NULL) + 1;
+	  bool removed_any = false;
+	  for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+	    /* This relies on l_scope[] entries being always set either
+	       to its own l_symbolic_searchlist address, or some map's
+	       l_searchlist address.  */
+	    if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
+	      {
+		struct link_map *tmap = (struct link_map *)
+		  ((char *) imap->l_scope[cnt]
+		   - offsetof (struct link_map, l_searchlist));
+		assert (tmap->l_ns == nsid);
+		if (tmap->l_idx == IDX_STILL_USED)
+		  ++remain;
+		else
+		  removed_any = true;
+	      }
+	    else
+	      ++remain;
+
+	  if (removed_any)
+	    {
+	      /* Always allocate a new array for the scope.  This is
+		 necessary since we must be able to determine the last
+		 user of the current array.  If possible use the link map's
+		 memory.  */
+	      size_t new_size;
+	      struct r_scope_elem **newp;
+
+#define SCOPE_ELEMS(imap) \
+  (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
+
+	      if (imap->l_scope != imap->l_scope_mem
+		  && remain < SCOPE_ELEMS (imap))
+		{
+		  new_size = SCOPE_ELEMS (imap);
+		  newp = imap->l_scope_mem;
+		}
+	      else
+		{
+		  new_size = imap->l_scope_max;
+		  newp = (struct r_scope_elem **)
+		    malloc (new_size * sizeof (struct r_scope_elem *));
+		  if (newp == NULL)
+		    _dl_signal_error (ENOMEM, "dlclose", NULL,
+				      N_("cannot create scope list"));
+		}
+
+	      /* Copy over the remaining scope elements.  */
+	      remain = 0;
+	      for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+		{
+		  if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
+		    {
+		      struct link_map *tmap = (struct link_map *)
+			((char *) imap->l_scope[cnt]
+			 - offsetof (struct link_map, l_searchlist));
+		      if (tmap->l_idx != IDX_STILL_USED)
+			{
+			  /* Remove the scope.  Or replace with own map's
+			     scope.  */
+			  if (new_list != NULL)
+			    {
+			      newp[remain++] = new_list;
+			      new_list = NULL;
+			    }
+			  continue;
+			}
+		    }
+
+		  newp[remain++] = imap->l_scope[cnt];
+		}
+	      newp[remain] = NULL;
+
+	      struct r_scope_elem **old = imap->l_scope;
+
+	      imap->l_scope = newp;
+
+	      /* No user anymore, we can free it now.  */
+	      if (old != imap->l_scope_mem)
+		{
+		  if (_dl_scope_free (old))
+		    /* If _dl_scope_free used THREAD_GSCOPE_WAIT (),
+		       no need to repeat it.  */
+		    scope_mem_left = false;
+		}
+	      else
+		scope_mem_left = true;
+
+	      imap->l_scope_max = new_size;
+	    }
+	  else if (new_list != NULL)
+	    {
+	      /* We didn't change the scope array, so reset the search
+		 list.  */
+	      imap->l_searchlist.r_list = NULL;
+	      imap->l_searchlist.r_nlist = 0;
+	    }
+
+	  /* The loader is gone, so mark the object as not having one.
+	     Note: l_idx != IDX_STILL_USED -> object will be removed.  */
+	  if (imap->l_loader != NULL
+	      && imap->l_loader->l_idx != IDX_STILL_USED)
+	    imap->l_loader = NULL;
+
+	  /* Remember where the first dynamically loaded object is.  */
+	  if (i < first_loaded)
+	    first_loaded = i;
+	}
+    }
+
+  /* If there are no objects to unload, do nothing further.  */
+  if (!unload_any)
+    goto out;
+
+#ifdef SHARED
+  /* Auditing checkpoint: we will start deleting objects.  */
+  if (__glibc_unlikely (do_audit))
+    {
+      struct link_map *head = ns->_ns_loaded;
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      /* Do not call the functions for any auditing object.  */
+      if (head->l_auditing == 0)
+	{
+	  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	    {
+	      if (afct->activity != NULL)
+		afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE);
+
+	      afct = afct->next;
+	    }
+	}
+    }
+#endif
+
+  /* Notify the debugger we are about to remove some loaded objects.  */
+  struct r_debug *r = _dl_debug_initialize (0, nsid);
+  r->r_state = RT_DELETE;
+  _dl_debug_state ();
+  LIBC_PROBE (unmap_start, 2, nsid, r);
+
+  if (unload_global)
+    {
+      /* Some objects are in the global scope list.  Remove them.  */
+      struct r_scope_elem *ns_msl = ns->_ns_main_searchlist;
+      unsigned int i;
+      unsigned int j = 0;
+      unsigned int cnt = ns_msl->r_nlist;
+
+      while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed)
+	--cnt;
+
+      if (cnt + unload_global == ns_msl->r_nlist)
+	/* Speed up removing most recently added objects.  */
+	j = cnt;
+      else
+	for (i = 0; i < cnt; i++)
+	  if (ns_msl->r_list[i]->l_removed == 0)
+	    {
+	      if (i != j)
+		ns_msl->r_list[j] = ns_msl->r_list[i];
+	      j++;
+	    }
+      ns_msl->r_nlist = j;
+    }
+
+  if (!RTLD_SINGLE_THREAD_P
+      && (unload_global
+	  || scope_mem_left
+	  || (GL(dl_scope_free_list) != NULL
+	      && GL(dl_scope_free_list)->count)))
+    {
+      THREAD_GSCOPE_WAIT ();
+
+      /* Now we can free any queued old scopes.  */
+      struct dl_scope_free_list *fsl = GL(dl_scope_free_list);
+      if (fsl != NULL)
+	while (fsl->count > 0)
+	  free (fsl->list[--fsl->count]);
+    }
+
+  size_t tls_free_start;
+  size_t tls_free_end;
+  tls_free_start = tls_free_end = NO_TLS_OFFSET;
+
+  /* We modify the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
+  /* Check each element of the search list to see if all references to
+     it are gone.  */
+  for (unsigned int i = first_loaded; i < nloaded; ++i)
+    {
+      struct link_map *imap = maps[i];
+      if (!used[i])
+	{
+	  assert (imap->l_type == lt_loaded);
+
+	  /* That was the last reference, and this was a dlopen-loaded
+	     object.  We can unmap it.  */
+
+	  /* Remove the object from the dtv slotinfo array if it uses TLS.  */
+	  if (__glibc_unlikely (imap->l_tls_blocksize > 0))
+	    {
+	      any_tls = true;
+
+	      if (GL(dl_tls_dtv_slotinfo_list) != NULL
+		  && ! remove_slotinfo (imap->l_tls_modid,
+					GL(dl_tls_dtv_slotinfo_list), 0,
+					imap->l_init_called))
+		/* All dynamically loaded modules with TLS are unloaded.  */
+		GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
+
+	      if (imap->l_tls_offset != NO_TLS_OFFSET
+		  && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET)
+		{
+		  /* Collect a contiguous chunk built from the objects in
+		     this search list, going in either direction.  When the
+		     whole chunk is at the end of the used area then we can
+		     reclaim it.  */
+#if TLS_TCB_AT_TP
+		  if (tls_free_start == NO_TLS_OFFSET
+		      || (size_t) imap->l_tls_offset == tls_free_start)
+		    {
+		      /* Extend the contiguous chunk being reclaimed.  */
+		      tls_free_start
+			= imap->l_tls_offset - imap->l_tls_blocksize;
+
+		      if (tls_free_end == NO_TLS_OFFSET)
+			tls_free_end = imap->l_tls_offset;
+		    }
+		  else if (imap->l_tls_offset - imap->l_tls_blocksize
+			   == tls_free_end)
+		    /* Extend the chunk backwards.  */
+		    tls_free_end = imap->l_tls_offset;
+		  else
+		    {
+		      /* This isn't contiguous with the last chunk freed.
+			 One of them will be leaked unless we can free
+			 one block right away.  */
+		      if (tls_free_end == GL(dl_tls_static_used))
+			{
+			  GL(dl_tls_static_used) = tls_free_start;
+			  tls_free_end = imap->l_tls_offset;
+			  tls_free_start
+			    = tls_free_end - imap->l_tls_blocksize;
+			}
+		      else if ((size_t) imap->l_tls_offset
+			       == GL(dl_tls_static_used))
+			GL(dl_tls_static_used)
+			  = imap->l_tls_offset - imap->l_tls_blocksize;
+		      else if (tls_free_end < (size_t) imap->l_tls_offset)
+			{
+			  /* We pick the later block.  It has a chance to
+			     be freed.  */
+			  tls_free_end = imap->l_tls_offset;
+			  tls_free_start
+			    = tls_free_end - imap->l_tls_blocksize;
+			}
+		    }
+#elif TLS_DTV_AT_TP
+		  if (tls_free_start == NO_TLS_OFFSET)
+		    {
+		      tls_free_start = imap->l_tls_firstbyte_offset;
+		      tls_free_end = (imap->l_tls_offset
+				      + imap->l_tls_blocksize);
+		    }
+		  else if (imap->l_tls_firstbyte_offset == tls_free_end)
+		    /* Extend the contiguous chunk being reclaimed.  */
+		    tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
+		  else if (imap->l_tls_offset + imap->l_tls_blocksize
+			   == tls_free_start)
+		    /* Extend the chunk backwards.  */
+		    tls_free_start = imap->l_tls_firstbyte_offset;
+		  /* This isn't contiguous with the last chunk freed.
+		     One of them will be leaked unless we can free
+		     one block right away.  */
+		  else if (imap->l_tls_offset + imap->l_tls_blocksize
+			   == GL(dl_tls_static_used))
+		    GL(dl_tls_static_used) = imap->l_tls_firstbyte_offset;
+		  else if (tls_free_end == GL(dl_tls_static_used))
+		    {
+		      GL(dl_tls_static_used) = tls_free_start;
+		      tls_free_start = imap->l_tls_firstbyte_offset;
+		      tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
+		    }
+		  else if (tls_free_end < imap->l_tls_firstbyte_offset)
+		    {
+		      /* We pick the later block.  It has a chance to
+			 be freed.  */
+		      tls_free_start = imap->l_tls_firstbyte_offset;
+		      tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
+		    }
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+		}
+	    }
+
+	  /* Reset unique symbols if forced.  */
+	  if (force)
+	    {
+	      struct unique_sym_table *tab = &ns->_ns_unique_sym_table;
+	      __rtld_lock_lock_recursive (tab->lock);
+	      struct unique_sym *entries = tab->entries;
+	      if (entries != NULL)
+		{
+		  size_t idx, size = tab->size;
+		  for (idx = 0; idx < size; ++idx)
+		    {
+		      /* Clear unique symbol entries that belong to this
+			 object.  */
+		      if (entries[idx].name != NULL
+			  && entries[idx].map == imap)
+			{
+			  entries[idx].name = NULL;
+			  entries[idx].hashval = 0;
+			  tab->n_elements--;
+			}
+		    }
+		}
+	      __rtld_lock_unlock_recursive (tab->lock);
+	    }
+
+	  /* We can unmap all the maps at once.  We determined the
+	     start address and length when we loaded the object and
+	     the `munmap' call does the rest.  */
+	  DL_UNMAP (imap);
+
+	  /* Finally, unlink the data structure and free it.  */
+#if DL_NNS == 1
+	  /* The assert in the (imap->l_prev == NULL) case gives
+	     the compiler license to warn that NS points outside
+	     the dl_ns array bounds in that case (as nsid != LM_ID_BASE
+	     is tantamount to nsid >= DL_NNS).  That should be impossible
+	     in this configuration, so just assert about it instead.  */
+	  assert (nsid == LM_ID_BASE);
+	  assert (imap->l_prev != NULL);
+#else
+	  if (imap->l_prev == NULL)
+	    {
+	      assert (nsid != LM_ID_BASE);
+	      ns->_ns_loaded = imap->l_next;
+
+	      /* Update the pointer to the head of the list
+		 we leave for debuggers to examine.  */
+	      r->r_map = (void *) ns->_ns_loaded;
+	    }
+	  else
+#endif
+	    imap->l_prev->l_next = imap->l_next;
+
+	  --ns->_ns_nloaded;
+	  if (imap->l_next != NULL)
+	    imap->l_next->l_prev = imap->l_prev;
+
+	  free (imap->l_versions);
+	  if (imap->l_origin != (char *) -1)
+	    free ((char *) imap->l_origin);
+
+	  free (imap->l_reldeps);
+
+	  /* Print debugging message.  */
+	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+	    _dl_debug_printf ("\nfile=%s [%lu];  destroying link map\n",
+			      imap->l_name, imap->l_ns);
+
+	  /* This name always is allocated.  */
+	  free (imap->l_name);
+	  /* Remove the list with all the names of the shared object.  */
+
+	  struct libname_list *lnp = imap->l_libname;
+	  do
+	    {
+	      struct libname_list *this = lnp;
+	      lnp = lnp->next;
+	      if (!this->dont_free)
+		free (this);
+	    }
+	  while (lnp != NULL);
+
+	  /* Remove the searchlists.  */
+	  free (imap->l_initfini);
+
+	  /* Remove the scope array if we allocated it.  */
+	  if (imap->l_scope != imap->l_scope_mem)
+	    free (imap->l_scope);
+
+	  if (imap->l_phdr_allocated)
+	    free ((void *) imap->l_phdr);
+
+	  if (imap->l_rpath_dirs.dirs != (void *) -1)
+	    free (imap->l_rpath_dirs.dirs);
+	  if (imap->l_runpath_dirs.dirs != (void *) -1)
+	    free (imap->l_runpath_dirs.dirs);
+
+	  free (imap);
+	}
+    }
+
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+
+  /* If we removed any object which uses TLS bump the generation counter.  */
+  if (any_tls)
+    {
+      if (__glibc_unlikely (++GL(dl_tls_generation) == 0))
+	_dl_fatal_printf ("TLS generation counter wrapped!  Please report as described in "REPORT_BUGS_TO".\n");
+
+      if (tls_free_end == GL(dl_tls_static_used))
+	GL(dl_tls_static_used) = tls_free_start;
+    }
+
+#ifdef SHARED
+  /* Auditing checkpoint: we have deleted all objects.  */
+  if (__glibc_unlikely (do_audit))
+    {
+      struct link_map *head = ns->_ns_loaded;
+      /* Do not call the functions for any auditing object.  */
+      if (head->l_auditing == 0)
+	{
+	  struct audit_ifaces *afct = GLRO(dl_audit);
+	  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	    {
+	      if (afct->activity != NULL)
+		afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+	      afct = afct->next;
+	    }
+	}
+    }
+#endif
+
+  if (__builtin_expect (ns->_ns_loaded == NULL, 0)
+      && nsid == GL(dl_nns) - 1)
+    do
+      --GL(dl_nns);
+    while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL);
+
+  /* Notify the debugger those objects are finalized and gone.  */
+  r->r_state = RT_CONSISTENT;
+  _dl_debug_state ();
+  LIBC_PROBE (unmap_complete, 2, nsid, r);
+
+  /* Recheck if we need to retry, release the lock.  */
+ out:
+  if (dl_close_state == rerun)
+    goto retry;
+
+  dl_close_state = not_pending;
+}
+
+
+void
+_dl_close (void *_map)
+{
+  struct link_map *map = _map;
+
+  /* We must take the lock to examine the contents of map and avoid
+     concurrent dlopens.  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  /* At this point we are guaranteed nobody else is touching the list of
+     loaded maps, but a concurrent dlclose might have freed our map
+     before we took the lock. There is no way to detect this (see below)
+     so we proceed assuming this isn't the case.  First see whether we
+     can remove the object at all.  */
+  if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
+    {
+      /* Nope.  Do nothing.  */
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+      return;
+    }
+
+  /* At present this is an unreliable check except in the case where the
+     caller has recursively called dlclose and we are sure the link map
+     has not been freed.  In a non-recursive dlclose the map itself
+     might have been freed and this access is potentially a data race
+     with whatever other use this memory might have now, or worse we
+     might silently corrupt memory if it looks enough like a link map.
+     POSIX has language in dlclose that appears to guarantee that this
+     should be a detectable case and given that dlclose should be threadsafe
+     we need this to be a reliable detection.
+     This is bug 20990. */
+  if (__builtin_expect (map->l_direct_opencount, 1) == 0)
+    {
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+      _dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
+    }
+
+  _dl_close_worker (map, false);
+
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+}
diff --git a/REORG.TODO/elf/dl-conflict.c b/REORG.TODO/elf/dl-conflict.c
new file mode 100644
index 0000000000..3cbd07435e
--- /dev/null
+++ b/REORG.TODO/elf/dl-conflict.c
@@ -0,0 +1,74 @@
+/* Resolve conflicts against already prelinked libraries.
+   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include "dynamic-link.h"
+
+void
+_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
+		       ElfW(Rela) *conflictend)
+{
+#if ! ELF_MACHINE_NO_RELA
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
+    _dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
+
+  {
+    /* Do the conflict relocation of the object and library GOT and other
+       data.  */
+
+    /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
+#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL)
+#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
+#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
+  do {									      \
+    while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset))	      \
+	   || (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset)))  \
+      resolve_conflict_map = resolve_conflict_map->l_next;		      \
+									      \
+    (map) = resolve_conflict_map;					      \
+  } while (0)
+
+    /* Prelinking makes no sense for anything but the main namespace.  */
+    assert (l->l_ns == LM_ID_BASE);
+    struct link_map *resolve_conflict_map __attribute__ ((__unused__))
+      = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+#include "dynamic-link.h"
+
+    /* Override these, defined in dynamic-link.h.  */
+#undef CHECK_STATIC_TLS
+#define CHECK_STATIC_TLS(ref_map, sym_map) ((void) 0)
+#undef TRY_STATIC_TLS
+#define TRY_STATIC_TLS(ref_map, sym_map) (0)
+
+    GL(dl_num_cache_relocations) += conflictend - conflict;
+
+    for (; conflict < conflictend; ++conflict)
+      elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset,
+			0);
+  }
+#endif
+}
diff --git a/REORG.TODO/elf/dl-debug.c b/REORG.TODO/elf/dl-debug.c
new file mode 100644
index 0000000000..f3957044f6
--- /dev/null
+++ b/REORG.TODO/elf/dl-debug.c
@@ -0,0 +1,76 @@
+/* Communicate dynamic linker state to the debugger at runtime.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+
+
+/* These are the members in the public `struct link_map' type.
+   Sanity check that the internal type and the public type match.  */
+#define VERIFY_MEMBER(name) \
+  (offsetof (struct link_map_public, name) == offsetof (struct link_map, name))
+extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
+					  && VERIFY_MEMBER (l_name)
+					  && VERIFY_MEMBER (l_ld)
+					  && VERIFY_MEMBER (l_next)
+					  && VERIFY_MEMBER (l_prev))
+					 ? 1 : -1];
+
+/* This structure communicates dl state to the debugger.  The debugger
+   normally finds it via the DT_DEBUG entry in the dynamic section, but in
+   a statically-linked program there is no dynamic section for the debugger
+   to examine and it looks for this particular symbol name.  */
+struct r_debug _r_debug;
+
+
+/* Initialize _r_debug if it has not already been done.  The argument is
+   the run-time load address of the dynamic linker, to be put in
+   _r_debug.r_ldbase.  Returns the address of _r_debug.  */
+
+struct r_debug *
+internal_function
+_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
+{
+  struct r_debug *r;
+
+  if (ns == LM_ID_BASE)
+    r = &_r_debug;
+  else
+    r = &GL(dl_ns)[ns]._ns_debug;
+
+  if (r->r_map == NULL || ldbase != 0)
+    {
+      /* Tell the debugger where to find the map of loaded objects.  */
+      r->r_version = 1	/* R_DEBUG_VERSION XXX */;
+      r->r_ldbase = ldbase ?: _r_debug.r_ldbase;
+      r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded;
+      r->r_brk = (ElfW(Addr)) &_dl_debug_state;
+    }
+
+  return r;
+}
+
+
+/* This function exists solely to have a breakpoint set on it by the
+   debugger.  The debugger is supposed to find this function's address by
+   examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
+   for this particular symbol name in the PT_INTERP file.  */
+void
+_dl_debug_state (void)
+{
+}
+rtld_hidden_def (_dl_debug_state)
diff --git a/REORG.TODO/elf/dl-deps.c b/REORG.TODO/elf/dl-deps.c
new file mode 100644
index 0000000000..1b8bac6593
--- /dev/null
+++ b/REORG.TODO/elf/dl-deps.c
@@ -0,0 +1,688 @@
+/* Load the dependencies of a mapped object.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <libintl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <ldsodefs.h>
+
+#include <dl-dst.h>
+
+/* Whether an shared object references one or more auxiliary objects
+   is signaled by the AUXTAG entry in l_info.  */
+#define AUXTAG	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+		 + DT_EXTRATAGIDX (DT_AUXILIARY))
+/* Whether an shared object references one or more auxiliary objects
+   is signaled by the AUXTAG entry in l_info.  */
+#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+		   + DT_EXTRATAGIDX (DT_FILTER))
+
+
+/* When loading auxiliary objects we must ignore errors.  It's ok if
+   an object is missing.  */
+struct openaux_args
+  {
+    /* The arguments to openaux.  */
+    struct link_map *map;
+    int trace_mode;
+    int open_mode;
+    const char *strtab;
+    const char *name;
+
+    /* The return value of openaux.  */
+    struct link_map *aux;
+  };
+
+static void
+openaux (void *a)
+{
+  struct openaux_args *args = (struct openaux_args *) a;
+
+  args->aux = _dl_map_object (args->map, args->name,
+			      (args->map->l_type == lt_executable
+			       ? lt_library : args->map->l_type),
+			      args->trace_mode, args->open_mode,
+			      args->map->l_ns);
+}
+
+static ptrdiff_t
+internal_function
+_dl_build_local_scope (struct link_map **list, struct link_map *map)
+{
+  struct link_map **p = list;
+  struct link_map **q;
+
+  *p++ = map;
+  map->l_reserved = 1;
+  if (map->l_initfini)
+    for (q = map->l_initfini + 1; *q; ++q)
+      if (! (*q)->l_reserved)
+	p += _dl_build_local_scope (p, *q);
+  return p - list;
+}
+
+
+/* We use a very special kind of list to track the path
+   through the list of loaded shared objects.  We have to
+   produce a flat list with unique members of all involved objects.
+*/
+struct list
+  {
+    int done;			/* Nonzero if this map was processed.  */
+    struct link_map *map;	/* The data.  */
+    struct list *next;		/* Elements for normal list.  */
+  };
+
+
+/* Macro to expand DST.  It is an macro since we use `alloca'.  */
+#define expand_dst(l, str, fatal) \
+  ({									      \
+    const char *__str = (str);						      \
+    const char *__result = __str;					      \
+    size_t __dst_cnt = DL_DST_COUNT (__str, 0);				      \
+									      \
+    if (__dst_cnt != 0)							      \
+      {									      \
+	char *__newp;							      \
+									      \
+	/* DST must not appear in SUID/SGID programs.  */		      \
+	if (__libc_enable_secure)					      \
+	  _dl_signal_error (0, __str, NULL, N_("\
+DST not allowed in SUID/SGID programs"));				      \
+									      \
+	__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
+						   __dst_cnt));		      \
+									      \
+	__result = _dl_dst_substitute (l, __str, __newp, 0);		      \
+									      \
+	if (*__result == '\0')						      \
+	  {								      \
+	    /* The replacement for the DST is not known.  We can't	      \
+	       processed.  */						      \
+	    if (fatal)							      \
+	      _dl_signal_error (0, __str, NULL, N_("\
+empty dynamic string token substitution"));				      \
+	    else							      \
+	      {								      \
+		/* This is for DT_AUXILIARY.  */			      \
+		if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))   \
+		  _dl_debug_printf (N_("\
+cannot load auxiliary `%s' because of empty dynamic string token "	      \
+					    "substitution\n"), __str);	      \
+		continue;						      \
+	      }								      \
+	  }								      \
+      }									      \
+									      \
+    __result; })
+
+static void
+preload (struct list *known, unsigned int *nlist, struct link_map *map)
+{
+  known[*nlist].done = 0;
+  known[*nlist].map = map;
+  known[*nlist].next = &known[*nlist + 1];
+
+  ++*nlist;
+  /* We use `l_reserved' as a mark bit to detect objects we have
+     already put in the search list and avoid adding duplicate
+     elements later in the list.  */
+  map->l_reserved = 1;
+}
+
+void
+internal_function
+_dl_map_object_deps (struct link_map *map,
+		     struct link_map **preloads, unsigned int npreloads,
+		     int trace_mode, int open_mode)
+{
+  struct list *known = __alloca (sizeof *known * (1 + npreloads + 1));
+  struct list *runp, *tail;
+  unsigned int nlist, i;
+  /* Object name.  */
+  const char *name;
+  int errno_saved;
+  int errno_reason;
+  const char *errstring;
+  const char *objname;
+
+  /* No loaded object so far.  */
+  nlist = 0;
+
+  /* First load MAP itself.  */
+  preload (known, &nlist, map);
+
+  /* Add the preloaded items after MAP but before any of its dependencies.  */
+  for (i = 0; i < npreloads; ++i)
+    preload (known, &nlist, preloads[i]);
+
+  /* Terminate the lists.  */
+  known[nlist - 1].next = NULL;
+
+  /* Pointer to last unique object.  */
+  tail = &known[nlist - 1];
+
+  /* No alloca'd space yet.  */
+  struct link_map **needed_space = NULL;
+  size_t needed_space_bytes = 0;
+
+  /* Process each element of the search list, loading each of its
+     auxiliary objects and immediate dependencies.  Auxiliary objects
+     will be added in the list before the object itself and
+     dependencies will be appended to the list as we step through it.
+     This produces a flat, ordered list that represents a
+     breadth-first search of the dependency tree.
+
+     The whole process is complicated by the fact that we better
+     should use alloca for the temporary list elements.  But using
+     alloca means we cannot use recursive function calls.  */
+  errno_saved = errno;
+  errno_reason = 0;
+  errstring = NULL;
+  errno = 0;
+  name = NULL;
+  for (runp = known; runp; )
+    {
+      struct link_map *l = runp->map;
+      struct link_map **needed = NULL;
+      unsigned int nneeded = 0;
+
+      /* Unless otherwise stated, this object is handled.  */
+      runp->done = 1;
+
+      /* Allocate a temporary record to contain the references to the
+	 dependencies of this object.  */
+      if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
+	  && l != map && l->l_ldnum > 0)
+	{
+	  size_t new_size = l->l_ldnum * sizeof (struct link_map *);
+
+	  if (new_size > needed_space_bytes)
+	    needed_space
+	      = extend_alloca (needed_space, needed_space_bytes, new_size);
+
+	  needed = needed_space;
+	}
+
+      if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
+	{
+	  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+	  struct openaux_args args;
+	  struct list *orig;
+	  const ElfW(Dyn) *d;
+
+	  args.strtab = strtab;
+	  args.map = l;
+	  args.trace_mode = trace_mode;
+	  args.open_mode = open_mode;
+	  orig = runp;
+
+	  for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
+	    if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
+	      {
+		/* Map in the needed object.  */
+		struct link_map *dep;
+
+		/* Recognize DSTs.  */
+		name = expand_dst (l, strtab + d->d_un.d_val, 0);
+		/* Store the tag in the argument structure.  */
+		args.name = name;
+
+		bool malloced;
+		int err = _dl_catch_error (&objname, &errstring, &malloced,
+					   openaux, &args);
+		if (__glibc_unlikely (errstring != NULL))
+		  {
+		    char *new_errstring = strdupa (errstring);
+		    objname = strdupa (objname);
+		    if (malloced)
+		      free ((char *) errstring);
+		    errstring = new_errstring;
+
+		    if (err)
+		      errno_reason = err;
+		    else
+		      errno_reason = -1;
+		    goto out;
+		  }
+		else
+		  dep = args.aux;
+
+		if (! dep->l_reserved)
+		  {
+		    /* Allocate new entry.  */
+		    struct list *newp;
+
+		    newp = alloca (sizeof (struct list));
+
+		    /* Append DEP to the list.  */
+		    newp->map = dep;
+		    newp->done = 0;
+		    newp->next = NULL;
+		    tail->next = newp;
+		    tail = newp;
+		    ++nlist;
+		    /* Set the mark bit that says it's already in the list.  */
+		    dep->l_reserved = 1;
+		  }
+
+		/* Remember this dependency.  */
+		if (needed != NULL)
+		  needed[nneeded++] = dep;
+	      }
+	    else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
+	      {
+		struct list *newp;
+
+		/* Recognize DSTs.  */
+		name = expand_dst (l, strtab + d->d_un.d_val,
+				   d->d_tag == DT_AUXILIARY);
+		/* Store the tag in the argument structure.  */
+		args.name = name;
+
+		/* Say that we are about to load an auxiliary library.  */
+		if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
+				      0))
+		  _dl_debug_printf ("load auxiliary object=%s"
+				    " requested by file=%s\n",
+				    name,
+				    DSO_FILENAME (l->l_name));
+
+		/* We must be prepared that the addressed shared
+		   object is not available.  For filter objects the dependency
+		   must be available.  */
+		bool malloced;
+		int err = _dl_catch_error (&objname, &errstring, &malloced,
+					openaux, &args);
+
+		if (__glibc_unlikely (errstring != NULL))
+		  {
+		    if (d->d_tag == DT_AUXILIARY)
+		      {
+			/* We are not interested in the error message.  */
+			assert (errstring != NULL);
+			if (malloced)
+			  free ((char *) errstring);
+
+			/* Simply ignore this error and continue the work.  */
+			continue;
+		      }
+		    else
+		      {
+
+			char *new_errstring = strdupa (errstring);
+			objname = strdupa (objname);
+			if (malloced)
+			  free ((char *) errstring);
+			errstring = new_errstring;
+
+			if (err)
+			  errno_reason = err;
+			else
+			  errno_reason = -1;
+			goto out;
+		      }
+		  }
+
+		/* The auxiliary object is actually available.
+		   Incorporate the map in all the lists.  */
+
+		/* Allocate new entry.  This always has to be done.  */
+		newp = alloca (sizeof (struct list));
+
+		/* We want to insert the new map before the current one,
+		   but we have no back links.  So we copy the contents of
+		   the current entry over.  Note that ORIG and NEWP now
+		   have switched their meanings.  */
+		memcpy (newp, orig, sizeof (*newp));
+
+		/* Initialize new entry.  */
+		orig->done = 0;
+		orig->map = args.aux;
+
+		/* Remember this dependency.  */
+		if (needed != NULL)
+		  needed[nneeded++] = args.aux;
+
+		/* We must handle two situations here: the map is new,
+		   so we must add it in all three lists.  If the map
+		   is already known, we have two further possibilities:
+		   - if the object is before the current map in the
+		   search list, we do nothing.  It is already found
+		   early
+		   - if the object is after the current one, we must
+		   move it just before the current map to make sure
+		   the symbols are found early enough
+		*/
+		if (args.aux->l_reserved)
+		  {
+		    /* The object is already somewhere in the list.
+		       Locate it first.  */
+		    struct list *late;
+
+		    /* This object is already in the search list we
+		       are building.  Don't add a duplicate pointer.
+		       Just added by _dl_map_object.  */
+		    for (late = newp; late->next != NULL; late = late->next)
+		      if (late->next->map == args.aux)
+			break;
+
+		    if (late->next != NULL)
+		      {
+			/* The object is somewhere behind the current
+			   position in the search path.  We have to
+			   move it to this earlier position.  */
+			orig->next = newp;
+
+			/* Now remove the later entry from the list
+			   and adjust the tail pointer.  */
+			if (tail == late->next)
+			  tail = late;
+			late->next = late->next->next;
+
+			/* We must move the object earlier in the chain.  */
+			if (args.aux->l_prev != NULL)
+			  args.aux->l_prev->l_next = args.aux->l_next;
+			if (args.aux->l_next != NULL)
+			  args.aux->l_next->l_prev = args.aux->l_prev;
+
+			args.aux->l_prev = newp->map->l_prev;
+			newp->map->l_prev = args.aux;
+			if (args.aux->l_prev != NULL)
+			  args.aux->l_prev->l_next = args.aux;
+			args.aux->l_next = newp->map;
+		      }
+		    else
+		      {
+			/* The object must be somewhere earlier in the
+			   list.  Undo to the current list element what
+			   we did above.  */
+			memcpy (orig, newp, sizeof (*newp));
+			continue;
+		      }
+		  }
+		else
+		  {
+		    /* This is easy.  We just add the symbol right here.  */
+		    orig->next = newp;
+		    ++nlist;
+		    /* Set the mark bit that says it's already in the list.  */
+		    args.aux->l_reserved = 1;
+
+		    /* The only problem is that in the double linked
+		       list of all objects we don't have this new
+		       object at the correct place.  Correct this here.  */
+		    if (args.aux->l_prev)
+		      args.aux->l_prev->l_next = args.aux->l_next;
+		    if (args.aux->l_next)
+		      args.aux->l_next->l_prev = args.aux->l_prev;
+
+		    args.aux->l_prev = newp->map->l_prev;
+		    newp->map->l_prev = args.aux;
+		    if (args.aux->l_prev != NULL)
+		      args.aux->l_prev->l_next = args.aux;
+		    args.aux->l_next = newp->map;
+		  }
+
+		/* Move the tail pointer if necessary.  */
+		if (orig == tail)
+		  tail = newp;
+
+		/* Move on the insert point.  */
+		orig = newp;
+	      }
+	}
+
+      /* Terminate the list of dependencies and store the array address.  */
+      if (needed != NULL)
+	{
+	  needed[nneeded++] = NULL;
+
+	  struct link_map **l_initfini = (struct link_map **)
+	    malloc ((2 * nneeded + 1) * sizeof needed[0]);
+	  if (l_initfini == NULL)
+	    _dl_signal_error (ENOMEM, map->l_name, NULL,
+			      N_("cannot allocate dependency list"));
+	  l_initfini[0] = l;
+	  memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]);
+	  memcpy (&l_initfini[nneeded + 1], l_initfini,
+		  nneeded * sizeof needed[0]);
+	  atomic_write_barrier ();
+	  l->l_initfini = l_initfini;
+	  l->l_free_initfini = 1;
+	}
+
+      /* If we have no auxiliary objects just go on to the next map.  */
+      if (runp->done)
+	do
+	  runp = runp->next;
+	while (runp != NULL && runp->done);
+    }
+
+ out:
+  if (errno == 0 && errno_saved != 0)
+    __set_errno (errno_saved);
+
+  struct link_map **old_l_initfini = NULL;
+  if (map->l_initfini != NULL && map->l_type == lt_loaded)
+    {
+      /* This object was previously loaded as a dependency and we have
+	 a separate l_initfini list.  We don't need it anymore.  */
+      assert (map->l_searchlist.r_list == NULL);
+      old_l_initfini = map->l_initfini;
+    }
+
+  /* Store the search list we built in the object.  It will be used for
+     searches in the scope of this object.  */
+  struct link_map **l_initfini =
+    (struct link_map **) malloc ((2 * nlist + 1)
+				 * sizeof (struct link_map *));
+  if (l_initfini == NULL)
+    _dl_signal_error (ENOMEM, map->l_name, NULL,
+		      N_("cannot allocate symbol search list"));
+
+
+  map->l_searchlist.r_list = &l_initfini[nlist + 1];
+  map->l_searchlist.r_nlist = nlist;
+
+  for (nlist = 0, runp = known; runp; runp = runp->next)
+    {
+      if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
+	/* This can happen when we trace the loading.  */
+	--map->l_searchlist.r_nlist;
+      else
+	map->l_searchlist.r_list[nlist++] = runp->map;
+
+      /* Now clear all the mark bits we set in the objects on the search list
+	 to avoid duplicates, so the next call starts fresh.  */
+      runp->map->l_reserved = 0;
+    }
+
+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0
+      && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
+    {
+      /* If we are to compute conflicts, we have to build local scope
+	 for each library, not just the ultimate loader.  */
+      for (i = 0; i < nlist; ++i)
+	{
+	  struct link_map *l = map->l_searchlist.r_list[i];
+	  unsigned int j, cnt;
+
+	  /* The local scope has been already computed.  */
+	  if (l == map
+	      || (l->l_local_scope[0]
+		  && l->l_local_scope[0]->r_nlist) != 0)
+	    continue;
+
+	  if (l->l_info[AUXTAG] || l->l_info[FILTERTAG])
+	    {
+	      /* As current DT_AUXILIARY/DT_FILTER implementation needs to be
+		 rewritten, no need to bother with prelinking the old
+		 implementation.  */
+	      _dl_signal_error (EINVAL, l->l_name, NULL, N_("\
+Filters not supported with LD_TRACE_PRELINKING"));
+	    }
+
+	  cnt = _dl_build_local_scope (l_initfini, l);
+	  assert (cnt <= nlist);
+	  for (j = 0; j < cnt; j++)
+	    {
+	      l_initfini[j]->l_reserved = 0;
+	      if (j && __builtin_expect (l_initfini[j]->l_info[DT_SYMBOLIC]
+					 != NULL, 0))
+		l->l_symbolic_in_local_scope = true;
+	    }
+
+	  l->l_local_scope[0] =
+	    (struct r_scope_elem *) malloc (sizeof (struct r_scope_elem)
+					    + (cnt
+					       * sizeof (struct link_map *)));
+	  if (l->l_local_scope[0] == NULL)
+	    _dl_signal_error (ENOMEM, map->l_name, NULL,
+			      N_("cannot allocate symbol search list"));
+	  l->l_local_scope[0]->r_nlist = cnt;
+	  l->l_local_scope[0]->r_list =
+	    (struct link_map **) (l->l_local_scope[0] + 1);
+	  memcpy (l->l_local_scope[0]->r_list, l_initfini,
+		  cnt * sizeof (struct link_map *));
+	}
+    }
+
+  /* Maybe we can remove some relocation dependencies now.  */
+  assert (map->l_searchlist.r_list[0] == map);
+  struct link_map_reldeps *l_reldeps = NULL;
+  if (map->l_reldeps != NULL)
+    {
+      for (i = 1; i < nlist; ++i)
+	map->l_searchlist.r_list[i]->l_reserved = 1;
+
+      struct link_map **list = &map->l_reldeps->list[0];
+      for (i = 0; i < map->l_reldeps->act; ++i)
+	if (list[i]->l_reserved)
+	  {
+	    /* Need to allocate new array of relocation dependencies.  */
+	    l_reldeps = malloc (sizeof (*l_reldeps)
+				+ map->l_reldepsmax
+				  * sizeof (struct link_map *));
+	    if (l_reldeps == NULL)
+	      /* Bad luck, keep the reldeps duplicated between
+		 map->l_reldeps->list and map->l_initfini lists.  */
+	      ;
+	    else
+	      {
+		unsigned int j = i;
+		memcpy (&l_reldeps->list[0], &list[0],
+			i * sizeof (struct link_map *));
+		for (i = i + 1; i < map->l_reldeps->act; ++i)
+		  if (!list[i]->l_reserved)
+		    l_reldeps->list[j++] = list[i];
+		l_reldeps->act = j;
+	      }
+	  }
+
+      for (i = 1; i < nlist; ++i)
+	map->l_searchlist.r_list[i]->l_reserved = 0;
+    }
+
+  /* Sort the initializer list to take dependencies into account.  The binary
+     itself will always be initialize last.  */
+  memcpy (l_initfini, map->l_searchlist.r_list,
+	  nlist * sizeof (struct link_map *));
+  if (__glibc_likely (nlist > 1))
+    {
+      /* We can skip looking for the binary itself which is at the front
+	 of the search list.  */
+      i = 1;
+      uint16_t seen[nlist];
+      memset (seen, 0, nlist * sizeof (seen[0]));
+      while (1)
+	{
+	  /* Keep track of which object we looked at this round.  */
+	  ++seen[i];
+	  struct link_map *thisp = l_initfini[i];
+
+	  /* Find the last object in the list for which the current one is
+	     a dependency and move the current object behind the object
+	     with the dependency.  */
+	  unsigned int k = nlist - 1;
+	  while (k > i)
+	    {
+	      struct link_map **runp = l_initfini[k]->l_initfini;
+	      if (runp != NULL)
+		/* Look through the dependencies of the object.  */
+		while (*runp != NULL)
+		  if (__glibc_unlikely (*runp++ == thisp))
+		    {
+		      /* Move the current object to the back past the last
+			 object with it as the dependency.  */
+		      memmove (&l_initfini[i], &l_initfini[i + 1],
+			       (k - i) * sizeof (l_initfini[0]));
+		      l_initfini[k] = thisp;
+
+		      if (seen[i + 1] > nlist - i)
+			{
+			  ++i;
+			  goto next_clear;
+			}
+
+		      uint16_t this_seen = seen[i];
+		      memmove (&seen[i], &seen[i + 1],
+			       (k - i) * sizeof (seen[0]));
+		      seen[k] = this_seen;
+
+		      goto next;
+		    }
+
+	      --k;
+	    }
+
+	  if (++i == nlist)
+	    break;
+	next_clear:
+	  memset (&seen[i], 0, (nlist - i) * sizeof (seen[0]));
+
+	next:;
+	}
+    }
+
+  /* Terminate the list of dependencies.  */
+  l_initfini[nlist] = NULL;
+  atomic_write_barrier ();
+  map->l_initfini = l_initfini;
+  map->l_free_initfini = 1;
+  if (l_reldeps != NULL)
+    {
+      atomic_write_barrier ();
+      void *old_l_reldeps = map->l_reldeps;
+      map->l_reldeps = l_reldeps;
+      _dl_scope_free (old_l_reldeps);
+    }
+  if (old_l_initfini != NULL)
+    _dl_scope_free (old_l_initfini);
+
+  if (errno_reason)
+    _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname,
+		      NULL, errstring);
+}
diff --git a/REORG.TODO/elf/dl-dst.h b/REORG.TODO/elf/dl-dst.h
new file mode 100644
index 0000000000..a96513d4dc
--- /dev/null
+++ b/REORG.TODO/elf/dl-dst.h
@@ -0,0 +1,74 @@
+/* Handling of dynamic sring tokens.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "trusted-dirs.h"
+
+/* Determine the number of DST elements in the name.  Only if IS_PATH is
+   nonzero paths are recognized (i.e., multiple, ':' separated filenames).  */
+#define DL_DST_COUNT(name, is_path) \
+  ({									      \
+    size_t __cnt = 0;							      \
+    const char *__sf = strchr (name, '$');				      \
+									      \
+    if (__glibc_unlikely (__sf != NULL))				      \
+      __cnt = _dl_dst_count (__sf, is_path);			      \
+									      \
+    __cnt; })
+
+
+#ifdef SHARED
+# define IS_RTLD(l) (l) == &GL(dl_rtld_map)
+#else
+# define IS_RTLD(l) 0
+#endif
+/* Guess from the number of DSTs the length of the result string.  */
+#define DL_DST_REQUIRED(l, name, len, cnt) \
+  ({									      \
+    size_t __len = (len);						      \
+    size_t __cnt = (cnt);						      \
+									      \
+    if (__cnt > 0)							      \
+      {									      \
+	size_t dst_len;							      \
+	/* Now we make a guess how many extra characters on top of the	      \
+	   length of S we need to represent the result.  We know that	      \
+	   we have CNT replacements.  Each at most can use		      \
+	     MAX (MAX (strlen (ORIGIN), strlen (_dl_platform)),		      \
+		  strlen (DL_DST_LIB))					      \
+	   minus 4 (which is the length of "$LIB").			      \
+									      \
+	   First get the origin string if it is not available yet.	      \
+	   This can only happen for the map of the executable or, when	      \
+	   auditing, in ld.so.  */					      \
+	if ((l)->l_origin == NULL)					      \
+	  {								      \
+	    assert ((l)->l_name[0] == '\0' || IS_RTLD (l));		      \
+	    (l)->l_origin = _dl_get_origin ();				      \
+	    dst_len = ((l)->l_origin && (l)->l_origin != (char *) -1	      \
+			  ? strlen ((l)->l_origin) : 0);		      \
+	  }								      \
+	else								      \
+	  dst_len = (l)->l_origin == (char *) -1			      \
+	    ? 0 : strlen ((l)->l_origin);				      \
+	dst_len = MAX (MAX (dst_len, GLRO(dl_platformlen)),		      \
+		       strlen (DL_DST_LIB));				      \
+	if (dst_len > 4)						      \
+	  __len += __cnt * (dst_len - 4);				      \
+      }									      \
+									      \
+    __len; })
diff --git a/REORG.TODO/elf/dl-environ.c b/REORG.TODO/elf/dl-environ.c
new file mode 100644
index 0000000000..cbffec8808
--- /dev/null
+++ b/REORG.TODO/elf/dl-environ.c
@@ -0,0 +1,85 @@
+/* Environment handling for dynamic loader.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+
+/* Walk through the environment of the process and return all entries
+   starting with `LD_'.  */
+char *
+internal_function
+_dl_next_ld_env_entry (char ***position)
+{
+  char **current = *position;
+  char *result = NULL;
+
+  while (*current != NULL)
+    {
+      if (__builtin_expect ((*current)[0] == 'L', 0)
+	  && (*current)[1] == 'D' && (*current)[2] == '_')
+	{
+	  result = &(*current)[3];
+
+	  /* Save current position for next visit.  */
+	  *position = ++current;
+
+	  break;
+	}
+
+      ++current;
+    }
+
+  return result;
+}
+
+
+/* In ld.so __environ is not exported.  */
+extern char **__environ attribute_hidden;
+
+int
+unsetenv (const char *name)
+{
+  char **ep;
+
+  ep = __environ;
+  while (*ep != NULL)
+    {
+      size_t cnt = 0;
+
+      while ((*ep)[cnt] == name[cnt] && name[cnt] != '\0')
+	++cnt;
+
+      if (name[cnt] == '\0' && (*ep)[cnt] == '=')
+	{
+	  /* Found it.  Remove this pointer by moving later ones to
+	     the front.  */
+	  char **dp = ep;
+
+	  do
+	    dp[0] = dp[1];
+	  while (*dp++);
+	  /* Continue the loop in case NAME appears again.  */
+	}
+      else
+	++ep;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/dl-error-minimal.c b/REORG.TODO/elf/dl-error-minimal.c
new file mode 100644
index 0000000000..384c9b0edc
--- /dev/null
+++ b/REORG.TODO/elf/dl-error-minimal.c
@@ -0,0 +1,23 @@
+/* Error handling for runtime dynamic linker, minimal version.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This version does lives in ld.so, does not use thread-local data
+   and supports _dl_signal_cerror and _dl_receive_error.  */
+
+#define DL_ERROR_BOOTSTRAP 1
+#include "dl-error-skeleton.c"
diff --git a/REORG.TODO/elf/dl-error-skeleton.c b/REORG.TODO/elf/dl-error-skeleton.c
new file mode 100644
index 0000000000..8e5888d4bd
--- /dev/null
+++ b/REORG.TODO/elf/dl-error-skeleton.c
@@ -0,0 +1,230 @@
+/* Template for error handling for runtime dynamic linker.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* The following macro needs to be defined before including this
+   skeleton file:
+
+   DL_ERROR_BOOTSTRAP
+
+     If 1, do not use TLS and implement _dl_signal_cerror and
+     _dl_receive_error.  If 0, TLS is used, and the variants with
+     error callbacks are not provided.  */
+
+
+#include <libintl.h>
+#include <setjmp.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <stdio.h>
+
+/* This structure communicates state between _dl_catch_error and
+   _dl_signal_error.  */
+struct catch
+  {
+    const char **objname;	/* Object/File name.  */
+    const char **errstring;	/* Error detail filled in here.  */
+    bool *malloced;		/* Nonzero if the string is malloced
+				   by the libc malloc.  */
+    volatile int *errcode;	/* Return value of _dl_signal_error.  */
+    jmp_buf env;		/* longjmp here on error.  */
+  };
+
+/* Multiple threads at once can use the `_dl_catch_error' function.  The
+   calls can come from `_dl_map_object_deps', `_dlerror_run', or from
+   any of the libc functionality which loads dynamic objects (NSS, iconv).
+   Therefore we have to be prepared to save the state in thread-local
+   memory.  */
+#if !DL_ERROR_BOOTSTRAP
+static __thread struct catch *catch_hook attribute_tls_model_ie;
+#else
+/* The version of this code in ld.so cannot use thread-local variables
+   and is used during bootstrap only.  */
+static struct catch *catch_hook;
+#endif
+
+/* This message we return as a last resort.  We define the string in a
+   variable since we have to avoid freeing it and so have to enable
+   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
+static const char _dl_out_of_memory[] = "out of memory";
+
+#if DL_ERROR_BOOTSTRAP
+/* This points to a function which is called when an continuable error is
+   received.  Unlike the handling of `catch' this function may return.
+   The arguments will be the `errstring' and `objname'.
+
+   Since this functionality is not used in normal programs (only in ld.so)
+   we do not care about multi-threaded programs here.  We keep this as a
+   global variable.  */
+static receiver_fct receiver;
+#endif /* DL_ERROR_BOOTSTRAP */
+
+void
+internal_function
+_dl_signal_error (int errcode, const char *objname, const char *occation,
+		  const char *errstring)
+{
+  struct catch *lcatch = catch_hook;
+
+  if (! errstring)
+    errstring = N_("DYNAMIC LINKER BUG!!!");
+
+  if (objname == NULL)
+    objname = "";
+  if (lcatch != NULL)
+    {
+      /* We are inside _dl_catch_error.  Return to it.  We have to
+	 duplicate the error string since it might be allocated on the
+	 stack.  The object name is always a string constant.  */
+      size_t len_objname = strlen (objname) + 1;
+      size_t len_errstring = strlen (errstring) + 1;
+
+      char *errstring_copy = malloc (len_objname + len_errstring);
+      if (errstring_copy != NULL)
+	{
+	  /* Make a copy of the object file name and the error string.  */
+	  *lcatch->objname = memcpy (__mempcpy (errstring_copy,
+						errstring, len_errstring),
+				     objname, len_objname);
+	  *lcatch->errstring = errstring_copy;
+
+	  /* If the main executable is relocated it means the libc's malloc
+	     is used.  */
+          bool malloced = true;
+#ifdef SHARED
+	  malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL
+                      && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0));
+#endif
+	  *lcatch->malloced = malloced;
+	}
+      else
+	{
+	  /* This is better than nothing.  */
+	  *lcatch->objname = "";
+	  *lcatch->errstring = _dl_out_of_memory;
+	  *lcatch->malloced = false;
+	}
+
+      *lcatch->errcode = errcode;
+
+      /* We do not restore the signal mask because none was saved.  */
+      __longjmp (lcatch->env[0].__jmpbuf, 1);
+    }
+  else
+    {
+      /* Lossage while resolving the program's own symbols is always fatal.  */
+      char buffer[1024];
+      _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
+			RTLD_PROGNAME,
+			occation ?: N_("error while loading shared libraries"),
+			objname, *objname ? ": " : "",
+			errstring, errcode ? ": " : "",
+			(errcode
+			 ? __strerror_r (errcode, buffer, sizeof buffer)
+			 : ""));
+    }
+}
+libc_hidden_def (_dl_signal_error)
+
+
+#if DL_ERROR_BOOTSTRAP
+void
+internal_function
+_dl_signal_cerror (int errcode, const char *objname, const char *occation,
+		   const char *errstring)
+{
+  if (__builtin_expect (GLRO(dl_debug_mask)
+			& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
+		      errstring, receiver ? "continued" : "fatal");
+
+  if (receiver)
+    {
+      /* We are inside _dl_receive_error.  Call the user supplied
+	 handler and resume the work.  The receiver will still be
+	 installed.  */
+      (*receiver) (errcode, objname, errstring);
+    }
+  else
+    _dl_signal_error (errcode, objname, occation, errstring);
+}
+#endif /* DL_ERROR_BOOTSTRAP */
+
+
+int
+internal_function
+_dl_catch_error (const char **objname, const char **errstring,
+		 bool *mallocedp, void (*operate) (void *), void *args)
+{
+  /* We need not handle `receiver' since setting a `catch' is handled
+     before it.  */
+
+  /* Only this needs to be marked volatile, because it is the only local
+     variable that gets changed between the setjmp invocation and the
+     longjmp call.  All others are just set here (before setjmp) and read
+     in _dl_signal_error (before longjmp).  */
+  volatile int errcode;
+
+  struct catch c;
+  /* Don't use an initializer since we don't need to clear C.env.  */
+  c.objname = objname;
+  c.errstring = errstring;
+  c.malloced = mallocedp;
+  c.errcode = &errcode;
+
+  struct catch *const old = catch_hook;
+  catch_hook = &c;
+
+  /* Do not save the signal mask.  */
+  if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0)
+    {
+      (*operate) (args);
+      catch_hook = old;
+      *objname = NULL;
+      *errstring = NULL;
+      *mallocedp = false;
+      return 0;
+    }
+
+  /* We get here only if we longjmp'd out of OPERATE.  _dl_signal_error has
+     already stored values into *OBJNAME, *ERRSTRING, and *MALLOCEDP.  */
+  catch_hook = old;
+  return errcode;
+}
+libc_hidden_def (_dl_catch_error)
+
+#if DL_ERROR_BOOTSTRAP
+void
+internal_function
+_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
+{
+  struct catch *old_catch = catch_hook;
+  receiver_fct old_receiver = receiver;
+
+  /* Set the new values.  */
+  catch_hook = NULL;
+  receiver = fct;
+
+  (*operate) (args);
+
+  catch_hook = old_catch;
+  receiver = old_receiver;
+}
+#endif /* DL_ERROR_BOOTSTRAP */
diff --git a/REORG.TODO/elf/dl-error.c b/REORG.TODO/elf/dl-error.c
new file mode 100644
index 0000000000..bfcbd5358b
--- /dev/null
+++ b/REORG.TODO/elf/dl-error.c
@@ -0,0 +1,27 @@
+/* Error handling for runtime dynamic linker, full version.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This implementation lives in libc.so because it uses thread-local
+   data, which is not available in ld.so.  It interposes the version
+   in dl-error-minimal.c after ld.so bootstrap.
+
+   The signal/catch mechanism is used by the audit framework, which
+   means that even in ld.so, not all errors are fatal.  */
+
+#define DL_ERROR_BOOTSTRAP 0
+#include "dl-error-skeleton.c"
diff --git a/REORG.TODO/elf/dl-execstack.c b/REORG.TODO/elf/dl-execstack.c
new file mode 100644
index 0000000000..875338bea5
--- /dev/null
+++ b/REORG.TODO/elf/dl-execstack.c
@@ -0,0 +1,31 @@
+/* Stack executability handling for GNU dynamic linker.  Stub version.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <errno.h>
+
+/* There is no portable way to know the bounds of the initial thread's stack
+   so as to mprotect it.  */
+
+int
+internal_function
+_dl_make_stack_executable (void **stack_endp)
+{
+  return ENOSYS;
+}
+rtld_hidden_def (_dl_make_stack_executable)
diff --git a/REORG.TODO/elf/dl-fini.c b/REORG.TODO/elf/dl-fini.c
new file mode 100644
index 0000000000..93b337bea1
--- /dev/null
+++ b/REORG.TODO/elf/dl-fini.c
@@ -0,0 +1,281 @@
+/* Call the termination functions of loaded shared objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <string.h>
+#include <ldsodefs.h>
+
+
+/* Type of the constructor functions.  */
+typedef void (*fini_t) (void);
+
+
+void
+internal_function
+_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
+{
+  /* A list of one element need not be sorted.  */
+  if (nmaps == 1)
+    return;
+
+  /* We can skip looking for the binary itself which is at the front
+     of the search list for the main namespace.  */
+  unsigned int i = ns == LM_ID_BASE;
+  uint16_t seen[nmaps];
+  memset (seen, 0, nmaps * sizeof (seen[0]));
+  while (1)
+    {
+      /* Keep track of which object we looked at this round.  */
+      ++seen[i];
+      struct link_map *thisp = maps[i];
+
+      /* Do not handle ld.so in secondary namespaces and object which
+	 are not removed.  */
+      if (thisp != thisp->l_real || thisp->l_idx == -1)
+	goto skip;
+
+      /* Find the last object in the list for which the current one is
+	 a dependency and move the current object behind the object
+	 with the dependency.  */
+      unsigned int k = nmaps - 1;
+      while (k > i)
+	{
+	  struct link_map **runp = maps[k]->l_initfini;
+	  if (runp != NULL)
+	    /* Look through the dependencies of the object.  */
+	    while (*runp != NULL)
+	      if (__glibc_unlikely (*runp++ == thisp))
+		{
+		move:
+		  /* Move the current object to the back past the last
+		     object with it as the dependency.  */
+		  memmove (&maps[i], &maps[i + 1],
+			   (k - i) * sizeof (maps[0]));
+		  maps[k] = thisp;
+
+		  if (used != NULL)
+		    {
+		      char here_used = used[i];
+		      memmove (&used[i], &used[i + 1],
+			       (k - i) * sizeof (used[0]));
+		      used[k] = here_used;
+		    }
+
+		  if (seen[i + 1] > nmaps - i)
+		    {
+		      ++i;
+		      goto next_clear;
+		    }
+
+		  uint16_t this_seen = seen[i];
+		  memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0]));
+		  seen[k] = this_seen;
+
+		  goto next;
+		}
+
+	  if (__glibc_unlikely (maps[k]->l_reldeps != NULL))
+	    {
+	      unsigned int m = maps[k]->l_reldeps->act;
+	      struct link_map **relmaps = &maps[k]->l_reldeps->list[0];
+
+	      /* Look through the relocation dependencies of the object.  */
+	      while (m-- > 0)
+		if (__glibc_unlikely (relmaps[m] == thisp))
+		  {
+		    /* If a cycle exists with a link time dependency,
+		       preserve the latter.  */
+		    struct link_map **runp = thisp->l_initfini;
+		    if (runp != NULL)
+		      while (*runp != NULL)
+			if (__glibc_unlikely (*runp++ == maps[k]))
+			  goto ignore;
+		    goto move;
+		  }
+	    ignore:;
+	    }
+
+	  --k;
+	}
+
+    skip:
+      if (++i == nmaps)
+	break;
+    next_clear:
+      memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
+
+    next:;
+    }
+}
+
+
+void
+internal_function
+_dl_fini (void)
+{
+  /* Lots of fun ahead.  We have to call the destructors for all still
+     loaded objects, in all namespaces.  The problem is that the ELF
+     specification now demands that dependencies between the modules
+     are taken into account.  I.e., the destructor for a module is
+     called before the ones for any of its dependencies.
+
+     To make things more complicated, we cannot simply use the reverse
+     order of the constructors.  Since the user might have loaded objects
+     using `dlopen' there are possibly several other modules with its
+     dependencies to be taken into account.  Therefore we have to start
+     determining the order of the modules once again from the beginning.  */
+
+  /* We run the destructors of the main namespaces last.  As for the
+     other namespaces, we pick run the destructors in them in reverse
+     order of the namespace ID.  */
+#ifdef SHARED
+  int do_audit = 0;
+ again:
+#endif
+  for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
+    {
+      /* Protect against concurrent loads and unloads.  */
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+      unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
+      /* No need to do anything for empty namespaces or those used for
+	 auditing DSOs.  */
+      if (nloaded == 0
+#ifdef SHARED
+	  || GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
+#endif
+	  )
+	__rtld_lock_unlock_recursive (GL(dl_load_lock));
+      else
+	{
+	  /* Now we can allocate an array to hold all the pointers and
+	     copy the pointers in.  */
+	  struct link_map *maps[nloaded];
+
+	  unsigned int i;
+	  struct link_map *l;
+	  assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
+	  for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
+	    /* Do not handle ld.so in secondary namespaces.  */
+	    if (l == l->l_real)
+	      {
+		assert (i < nloaded);
+
+		maps[i] = l;
+		l->l_idx = i;
+		++i;
+
+		/* Bump l_direct_opencount of all objects so that they
+		   are not dlclose()ed from underneath us.  */
+		++l->l_direct_opencount;
+	      }
+	  assert (ns != LM_ID_BASE || i == nloaded);
+	  assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
+	  unsigned int nmaps = i;
+
+	  /* Now we have to do the sorting.  */
+	  _dl_sort_fini (maps, nmaps, NULL, ns);
+
+	  /* We do not rely on the linked list of loaded object anymore
+	     from this point on.  We have our own list here (maps).  The
+	     various members of this list cannot vanish since the open
+	     count is too high and will be decremented in this loop.  So
+	     we release the lock so that some code which might be called
+	     from a destructor can directly or indirectly access the
+	     lock.  */
+	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+	  /* 'maps' now contains the objects in the right order.  Now
+	     call the destructors.  We have to process this array from
+	     the front.  */
+	  for (i = 0; i < nmaps; ++i)
+	    {
+	      struct link_map *l = maps[i];
+
+	      if (l->l_init_called)
+		{
+		  /* Make sure nothing happens if we are called twice.  */
+		  l->l_init_called = 0;
+
+		  /* Is there a destructor function?  */
+		  if (l->l_info[DT_FINI_ARRAY] != NULL
+		      || l->l_info[DT_FINI] != NULL)
+		    {
+		      /* When debugging print a message first.  */
+		      if (__builtin_expect (GLRO(dl_debug_mask)
+					    & DL_DEBUG_IMPCALLS, 0))
+			_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+					  DSO_FILENAME (l->l_name),
+					  ns);
+
+		      /* First see whether an array is given.  */
+		      if (l->l_info[DT_FINI_ARRAY] != NULL)
+			{
+			  ElfW(Addr) *array =
+			    (ElfW(Addr) *) (l->l_addr
+					    + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
+			  unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
+					    / sizeof (ElfW(Addr)));
+			  while (i-- > 0)
+			    ((fini_t) array[i]) ();
+			}
+
+		      /* Next try the old-style destructor.  */
+		      if (l->l_info[DT_FINI] != NULL)
+			DL_CALL_DT_FINI
+			  (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
+		    }
+
+#ifdef SHARED
+		  /* Auditing checkpoint: another object closed.  */
+		  if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0))
+		    {
+		      struct audit_ifaces *afct = GLRO(dl_audit);
+		      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+			{
+			  if (afct->objclose != NULL)
+			    /* Return value is ignored.  */
+			    (void) afct->objclose (&l->l_audit[cnt].cookie);
+
+			  afct = afct->next;
+			}
+		    }
+#endif
+		}
+
+	      /* Correct the previous increment.  */
+	      --l->l_direct_opencount;
+	    }
+	}
+    }
+
+#ifdef SHARED
+  if (! do_audit && GLRO(dl_naudit) > 0)
+    {
+      do_audit = 1;
+      goto again;
+    }
+
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
+    _dl_debug_printf ("\nruntime linker statistics:\n"
+		      "           final number of relocations: %lu\n"
+		      "final number of relocations from cache: %lu\n",
+		      GL(dl_num_relocations),
+		      GL(dl_num_cache_relocations));
+#endif
+}
diff --git a/REORG.TODO/elf/dl-fptr.c b/REORG.TODO/elf/dl-fptr.c
new file mode 100644
index 0000000000..bf8ae43b51
--- /dev/null
+++ b/REORG.TODO/elf/dl-fptr.c
@@ -0,0 +1,322 @@
+/* Manage function descriptors.  Generic version.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <libintl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <link.h>
+#include <ldsodefs.h>
+#include <elf/dynamic-link.h>
+#include <dl-fptr.h>
+#include <dl-unmap-segments.h>
+#include <atomic.h>
+
+#ifndef ELF_MACHINE_BOOT_FPTR_TABLE_LEN
+/* ELF_MACHINE_BOOT_FPTR_TABLE_LEN should be greater than the number of
+   dynamic symbols in ld.so.  */
+# define ELF_MACHINE_BOOT_FPTR_TABLE_LEN 256
+#endif
+
+#ifndef ELF_MACHINE_LOAD_ADDRESS
+# error "ELF_MACHINE_LOAD_ADDRESS is not defined."
+#endif
+
+#ifndef COMPARE_AND_SWAP
+# define COMPARE_AND_SWAP(ptr, old, new) \
+  (catomic_compare_and_exchange_bool_acq (ptr, new, old) == 0)
+#endif
+
+ElfW(Addr) _dl_boot_fptr_table [ELF_MACHINE_BOOT_FPTR_TABLE_LEN];
+
+static struct local
+  {
+    struct fdesc_table *root;
+    struct fdesc *free_list;
+    unsigned int npages;		/* # of pages to allocate */
+    /* the next to members MUST be consecutive! */
+    struct fdesc_table boot_table;
+    struct fdesc boot_fdescs[1024];
+  }
+local =
+  {
+    .root = &local.boot_table,
+    .npages = 2,
+    .boot_table =
+      {
+	.len = sizeof (local.boot_fdescs) / sizeof (local.boot_fdescs[0]),
+	.first_unused = 0
+      }
+  };
+
+/* Create a new fdesc table and return a pointer to the first fdesc
+   entry.  The fdesc lock must have been acquired already.  */
+
+static struct fdesc_table *
+new_fdesc_table (struct local *l, size_t *size)
+{
+  size_t old_npages = l->npages;
+  size_t new_npages = old_npages + old_npages;
+  struct fdesc_table *new_table;
+
+  /* If someone has just created a new table, we return NULL to tell
+     the caller to use the new table.  */
+  if (! COMPARE_AND_SWAP (&l->npages, old_npages, new_npages))
+    return (struct fdesc_table *) NULL;
+
+  *size = old_npages * GLRO(dl_pagesize);
+  new_table = __mmap (NULL, *size,
+		      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+  if (new_table == MAP_FAILED)
+    _dl_signal_error (errno, NULL, NULL,
+		      N_("cannot map pages for fdesc table"));
+
+  new_table->len
+    = (*size - sizeof (*new_table)) / sizeof (struct fdesc);
+  new_table->first_unused = 1;
+  return new_table;
+}
+
+
+static ElfW(Addr)
+make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp)
+{
+  struct fdesc *fdesc = NULL;
+  struct fdesc_table *root;
+  unsigned int old;
+  struct local *l;
+
+  ELF_MACHINE_LOAD_ADDRESS (l, local);
+
+ retry:
+  root = l->root;
+  while (1)
+    {
+      old = root->first_unused;
+      if (old >= root->len)
+	break;
+      else if (COMPARE_AND_SWAP (&root->first_unused, old, old + 1))
+	{
+	  fdesc = &root->fdesc[old];
+	  goto install;
+	}
+    }
+
+  if (l->free_list)
+    {
+      /* Get it from free-list.  */
+      do
+	{
+	  fdesc = l->free_list;
+	  if (fdesc == NULL)
+	    goto retry;
+	}
+      while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->free_list,
+				 (ElfW(Addr)) fdesc, fdesc->ip));
+    }
+  else
+    {
+      /* Create a new fdesc table.  */
+      size_t size;
+      struct fdesc_table *new_table = new_fdesc_table (l, &size);
+
+      if (new_table == NULL)
+	goto retry;
+
+      new_table->next = root;
+      if (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->root,
+			      (ElfW(Addr)) root,
+			      (ElfW(Addr)) new_table))
+	{
+	  /* Someone has just installed a new table. Return NULL to
+	     tell the caller to use the new table.  */
+	  __munmap (new_table, size);
+	  goto retry;
+	}
+
+      /* Note that the first entry was reserved while allocating the
+	 memory for the new page.  */
+      fdesc = &new_table->fdesc[0];
+    }
+
+ install:
+  fdesc->ip = ip;
+  fdesc->gp = gp;
+
+  return (ElfW(Addr)) fdesc;
+}
+
+
+static inline ElfW(Addr) * __attribute__ ((always_inline))
+make_fptr_table (struct link_map *map)
+{
+  const ElfW(Sym) *symtab
+    = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+  ElfW(Addr) *fptr_table;
+  size_t size;
+  size_t len;
+
+  /* XXX Apparently the only way to find out the size of the dynamic
+     symbol section is to assume that the string table follows right
+     afterwards...  */
+  len = ((strtab - (char *) symtab)
+	 / map->l_info[DT_SYMENT]->d_un.d_val);
+  size = ((len * sizeof (fptr_table[0]) + GLRO(dl_pagesize) - 1)
+	  & -GLRO(dl_pagesize));
+  /* XXX We don't support here in the moment systems without MAP_ANON.
+     There probably are none for IA-64.  In case this is proven wrong
+     we will have to open /dev/null here and use the file descriptor
+     instead of the hard-coded -1.  */
+  fptr_table = __mmap (NULL, size,
+		       PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+		       -1, 0);
+  if (fptr_table == MAP_FAILED)
+    _dl_signal_error (errno, NULL, NULL,
+		      N_("cannot map pages for fptr table"));
+
+  if (COMPARE_AND_SWAP ((ElfW(Addr) *) &map->l_mach.fptr_table,
+			(ElfW(Addr)) NULL, (ElfW(Addr)) fptr_table))
+    map->l_mach.fptr_table_len = len;
+  else
+    __munmap (fptr_table, len * sizeof (fptr_table[0]));
+
+  return map->l_mach.fptr_table;
+}
+
+
+ElfW(Addr)
+_dl_make_fptr (struct link_map *map, const ElfW(Sym) *sym,
+	       ElfW(Addr) ip)
+{
+  ElfW(Addr) *ftab = map->l_mach.fptr_table;
+  const ElfW(Sym) *symtab;
+  Elf_Symndx symidx;
+  struct local *l;
+
+  if (__glibc_unlikely (ftab == NULL))
+    ftab = make_fptr_table (map);
+
+  symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  symidx = sym - symtab;
+
+  if (symidx >= map->l_mach.fptr_table_len)
+    _dl_signal_error (0, NULL, NULL,
+		      N_("internal error: symidx out of range of fptr table"));
+
+  while (ftab[symidx] == 0)
+    {
+      /* GOT has already been relocated in elf_get_dynamic_info -
+	 don't try to relocate it again.  */
+      ElfW(Addr) fdesc
+	= make_fdesc (ip, map->l_info[DT_PLTGOT]->d_un.d_ptr);
+
+      if (__builtin_expect (COMPARE_AND_SWAP (&ftab[symidx], (ElfW(Addr)) NULL,
+					      fdesc), 1))
+	{
+	  /* Noone has updated the entry and the new function
+	     descriptor has been installed.  */
+#if 0
+	  const char *strtab
+	    = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+	  ELF_MACHINE_LOAD_ADDRESS (l, local);
+	  if (l->root != &l->boot_table
+	      || l->boot_table.first_unused > 20)
+	    _dl_debug_printf ("created fdesc symbol `%s' at %lx\n",
+			      strtab + sym->st_name, ftab[symidx]);
+#endif
+	  break;
+	}
+      else
+	{
+	  /* We created a duplicated function descriptor. We put it on
+	     free-list.  */
+	  struct fdesc *f = (struct fdesc *) fdesc;
+
+	  ELF_MACHINE_LOAD_ADDRESS (l, local);
+
+	  do
+	    f->ip = (ElfW(Addr)) l->free_list;
+	  while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->free_list,
+				     f->ip, fdesc));
+	}
+    }
+
+  return ftab[symidx];
+}
+
+
+void
+_dl_unmap (struct link_map *map)
+{
+  ElfW(Addr) *ftab = map->l_mach.fptr_table;
+  struct fdesc *head = NULL, *tail = NULL;
+  size_t i;
+
+  _dl_unmap_segments (map);
+
+  if (ftab == NULL)
+    return;
+
+  /* String together the fdesc structures that are being freed.  */
+  for (i = 0; i < map->l_mach.fptr_table_len; ++i)
+    {
+      if (ftab[i])
+	{
+	  *(struct fdesc **) ftab[i] = head;
+	  head = (struct fdesc *) ftab[i];
+	  if (tail == NULL)
+	    tail = head;
+	}
+    }
+
+  /* Prepend the new list to the free_list: */
+  if (tail)
+    do
+      tail->ip = (ElfW(Addr)) local.free_list;
+    while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &local.free_list,
+			       tail->ip, (ElfW(Addr)) head));
+
+  __munmap (ftab, (map->l_mach.fptr_table_len
+		   * sizeof (map->l_mach.fptr_table[0])));
+
+  map->l_mach.fptr_table = NULL;
+}
+
+
+ElfW(Addr)
+_dl_lookup_address (const void *address)
+{
+  ElfW(Addr) addr = (ElfW(Addr)) address;
+  struct fdesc_table *t;
+  unsigned long int i;
+
+  for (t = local.root; t != NULL; t = t->next)
+    {
+      i = (struct fdesc *) addr - &t->fdesc[0];
+      if (i < t->first_unused && addr == (ElfW(Addr)) &t->fdesc[i])
+	{
+	  addr = t->fdesc[i].ip;
+	  break;
+	}
+    }
+
+  return addr;
+}
diff --git a/REORG.TODO/elf/dl-hwcaps.c b/REORG.TODO/elf/dl-hwcaps.c
new file mode 100644
index 0000000000..ac50fd2c38
--- /dev/null
+++ b/REORG.TODO/elf/dl-hwcaps.c
@@ -0,0 +1,297 @@
+/* Hardware capability support for run-time dynamic loader.
+   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <elf.h>
+#include <errno.h>
+#include <libintl.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+
+#include <dl-procinfo.h>
+#include <dl-hwcaps.h>
+
+#ifdef _DL_FIRST_PLATFORM
+# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
+#else
+# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
+#endif
+
+/* Return an array of useful/necessary hardware capability names.  */
+const struct r_strlenpair *
+internal_function
+_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
+		      size_t *max_capstrlen)
+{
+  uint64_t hwcap_mask = GET_HWCAP_MASK();
+  /* Determine how many important bits are set.  */
+  uint64_t masked = GLRO(dl_hwcap) & hwcap_mask;
+  size_t cnt = platform != NULL;
+  size_t n, m;
+  size_t total;
+  struct r_strlenpair *result;
+  struct r_strlenpair *rp;
+  char *cp;
+
+  /* Count the number of bits set in the masked value.  */
+  for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n)
+    if ((masked & (1ULL << n)) != 0)
+      ++cnt;
+
+#ifdef NEED_DL_SYSINFO_DSO
+  /* The system-supplied DSO can contain a note of type 2, vendor "GNU".
+     This gives us a list of names to treat as fake hwcap bits.  */
+
+  const char *dsocaps = NULL;
+  size_t dsocapslen = 0;
+  if (GLRO(dl_sysinfo_map) != NULL)
+    {
+      const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
+      const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
+      for (uint_fast16_t i = 0; i < phnum; ++i)
+	if (phdr[i].p_type == PT_NOTE)
+	  {
+	    const ElfW(Addr) start = (phdr[i].p_vaddr
+				      + GLRO(dl_sysinfo_map)->l_addr);
+	    /* The standard ELF note layout is exactly as the anonymous struct.
+	       The next element is a variable length vendor name of length
+	       VENDORLEN (with a real length rounded to ElfW(Word)), followed
+	       by the data of length DATALEN (with a real length rounded to
+	       ElfW(Word)).  */
+	    const struct
+	    {
+	      ElfW(Word) vendorlen;
+	      ElfW(Word) datalen;
+	      ElfW(Word) type;
+	    } *note = (const void *) start;
+	    while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
+	      {
+#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+		/* The layout of the type 2, vendor "GNU" note is as follows:
+		   .long <Number of capabilities enabled by this note>
+		   .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
+		   .byte <The bit number for the next capability>
+		   .asciz <The name of the capability>.  */
+		if (note->type == NT_GNU_HWCAP
+		    && note->vendorlen == sizeof "GNU"
+		    && !memcmp ((note + 1), "GNU", sizeof "GNU")
+		    && note->datalen > 2 * sizeof (ElfW(Word)) + 2)
+		  {
+		    const ElfW(Word) *p = ((const void *) (note + 1)
+					   + ROUND (sizeof "GNU"));
+		    cnt += *p++;
+		    ++p;	/* Skip mask word.  */
+		    dsocaps = (const char *) p; /* Pseudo-string "<b>name"  */
+		    dsocapslen = note->datalen - sizeof *p * 2;
+		    break;
+		  }
+		note = ((const void *) (note + 1)
+			+ ROUND (note->vendorlen) + ROUND (note->datalen));
+#undef ROUND
+	      }
+	    if (dsocaps != NULL)
+	      break;
+	  }
+    }
+#endif
+
+  /* For TLS enabled builds always add 'tls'.  */
+  ++cnt;
+
+  /* Create temporary data structure to generate result table.  */
+  struct r_strlenpair temp[cnt];
+  m = 0;
+#ifdef NEED_DL_SYSINFO_DSO
+  if (dsocaps != NULL)
+    {
+      /* dsocaps points to the .asciz string, and -1 points to the mask
+         .long just before the string.  */
+      const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
+      GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
+      /* Note that we add the dsocaps to the set already chosen by the
+	 LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT).
+	 So there is no way to request ignoring an OS-supplied dsocap
+	 string and bit like you can ignore an OS-supplied HWCAP bit.  */
+      hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA;
+#if HAVE_TUNABLES
+      TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask);
+#else
+      GLRO(dl_hwcap_mask) = hwcap_mask;
+#endif
+      size_t len;
+      for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1)
+	{
+	  uint_fast8_t bit = *p++;
+	  len = strlen (p);
+
+	  /* Skip entries that are not enabled in the mask word.  */
+	  if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit)))
+	    {
+	      temp[m].str = p;
+	      temp[m].len = len;
+	      ++m;
+	    }
+	  else
+	    --cnt;
+	}
+    }
+#endif
+  for (n = 0; masked != 0; ++n)
+    if ((masked & (1ULL << n)) != 0)
+      {
+	temp[m].str = _dl_hwcap_string (n);
+	temp[m].len = strlen (temp[m].str);
+	masked ^= 1ULL << n;
+	++m;
+      }
+  if (platform != NULL)
+    {
+      temp[m].str = platform;
+      temp[m].len = platform_len;
+      ++m;
+    }
+
+  temp[m].str = "tls";
+  temp[m].len = 3;
+  ++m;
+
+  assert (m == cnt);
+
+  /* Determine the total size of all strings together.  */
+  if (cnt == 1)
+    total = temp[0].len + 1;
+  else
+    {
+      total = temp[0].len + temp[cnt - 1].len + 2;
+      if (cnt > 2)
+	{
+	  total <<= 1;
+	  for (n = 1; n + 1 < cnt; ++n)
+	    total += temp[n].len + 1;
+	  if (cnt > 3
+	      && (cnt >= sizeof (size_t) * 8
+		  || total + (sizeof (*result) << 3)
+		     >= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
+	    _dl_signal_error (ENOMEM, NULL, NULL,
+			      N_("cannot create capability list"));
+
+	  total <<= cnt - 3;
+	}
+    }
+
+  /* The result structure: we use a very compressed way to store the
+     various combinations of capability names.  */
+  *sz = 1 << cnt;
+  result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
+  if (result == NULL)
+    _dl_signal_error (ENOMEM, NULL, NULL,
+		      N_("cannot create capability list"));
+
+  if (cnt == 1)
+    {
+      result[0].str = (char *) (result + *sz);
+      result[0].len = temp[0].len + 1;
+      result[1].str = (char *) (result + *sz);
+      result[1].len = 0;
+      cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
+      *cp = '/';
+      *sz = 2;
+      *max_capstrlen = result[0].len;
+
+      return result;
+    }
+
+  /* Fill in the information.  This follows the following scheme
+     (indices from TEMP for four strings):
+	entry #0: 0, 1, 2, 3	binary: 1111
+	      #1: 0, 1, 3		1101
+	      #2: 0, 2, 3		1011
+	      #3: 0, 3			1001
+     This allows the representation of all possible combinations of
+     capability names in the string.  First generate the strings.  */
+  result[1].str = result[0].str = cp = (char *) (result + *sz);
+#define add(idx) \
+      cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
+  if (cnt == 2)
+    {
+      add (1);
+      add (0);
+    }
+  else
+    {
+      n = 1 << (cnt - 1);
+      do
+	{
+	  n -= 2;
+
+	  /* We always add the last string.  */
+	  add (cnt - 1);
+
+	  /* Add the strings which have the bit set in N.  */
+	  for (m = cnt - 2; m > 0; --m)
+	    if ((n & (1 << m)) != 0)
+	      add (m);
+
+	  /* Always add the first string.  */
+	  add (0);
+	}
+      while (n != 0);
+    }
+#undef add
+
+  /* Now we are ready to install the string pointers and length.  */
+  for (n = 0; n < (1UL << cnt); ++n)
+    result[n].len = 0;
+  n = cnt;
+  do
+    {
+      size_t mask = 1 << --n;
+
+      rp = result;
+      for (m = 1 << cnt; m > 0; ++rp)
+	if ((--m & mask) != 0)
+	  rp->len += temp[n].len + 1;
+    }
+  while (n != 0);
+
+  /* The first half of the strings all include the first string.  */
+  n = (1 << cnt) - 2;
+  rp = &result[2];
+  while (n != (1UL << (cnt - 1)))
+    {
+      if ((--n & 1) != 0)
+	rp[0].str = rp[-2].str + rp[-2].len;
+      else
+	rp[0].str = rp[-1].str;
+      ++rp;
+    }
+
+  /* The second half starts right after the first part of the string of
+     the corresponding entry in the first half.  */
+  do
+    {
+      rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
+      ++rp;
+    }
+  while (--n != 0);
+
+  /* The maximum string length.  */
+  *max_capstrlen = result[0].len;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/dl-hwcaps.h b/REORG.TODO/elf/dl-hwcaps.h
new file mode 100644
index 0000000000..2c4fa3db02
--- /dev/null
+++ b/REORG.TODO/elf/dl-hwcaps.h
@@ -0,0 +1,30 @@
+/* Hardware capability support for run-time dynamic loader.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf/dl-tunables.h>
+
+#if HAVE_TUNABLES
+# define GET_HWCAP_MASK() TUNABLE_GET (glibc, tune, hwcap_mask, uint64_t, NULL)
+#else
+# ifdef SHARED
+#   define GET_HWCAP_MASK() GLRO(dl_hwcap_mask)
+# else
+/* HWCAP_MASK is ignored in static binaries when built without tunables.  */
+#  define GET_HWCAP_MASK() (0)
+# endif
+#endif
diff --git a/REORG.TODO/elf/dl-init.c b/REORG.TODO/elf/dl-init.c
new file mode 100644
index 0000000000..5c5f3de365
--- /dev/null
+++ b/REORG.TODO/elf/dl-init.c
@@ -0,0 +1,126 @@
+/* Run initializers for newly loaded objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <ldsodefs.h>
+
+
+/* Type of the initializer.  */
+typedef void (*init_t) (int, char **, char **);
+
+
+static void
+call_init (struct link_map *l, int argc, char **argv, char **env)
+{
+  if (l->l_init_called)
+    /* This object is all done.  */
+    return;
+
+  /* Avoid handling this constructor again in case we have a circular
+     dependency.  */
+  l->l_init_called = 1;
+
+  /* Check for object which constructors we do not run here.  */
+  if (__builtin_expect (l->l_name[0], 'a') == '\0'
+      && l->l_type == lt_executable)
+    return;
+
+  /* Are there any constructors?  */
+  if (l->l_info[DT_INIT] == NULL
+      && __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
+    return;
+
+  /* Print a debug message if wanted.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
+    _dl_debug_printf ("\ncalling init: %s\n\n",
+		      DSO_FILENAME (l->l_name));
+
+  /* Now run the local constructors.  There are two forms of them:
+     - the one named by DT_INIT
+     - the others in the DT_INIT_ARRAY.
+  */
+  if (l->l_info[DT_INIT] != NULL)
+    DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr, argc, argv, env);
+
+  /* Next see whether there is an array with initialization functions.  */
+  ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
+  if (init_array != NULL)
+    {
+      unsigned int j;
+      unsigned int jm;
+      ElfW(Addr) *addrs;
+
+      jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
+
+      addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
+      for (j = 0; j < jm; ++j)
+	((init_t) addrs[j]) (argc, argv, env);
+    }
+}
+
+
+void
+internal_function
+_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
+{
+  ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
+  ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
+  unsigned int i;
+
+  if (__glibc_unlikely (GL(dl_initfirst) != NULL))
+    {
+      call_init (GL(dl_initfirst), argc, argv, env);
+      GL(dl_initfirst) = NULL;
+    }
+
+  /* Don't do anything if there is no preinit array.  */
+  if (__builtin_expect (preinit_array != NULL, 0)
+      && preinit_array_size != NULL
+      && (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
+    {
+      ElfW(Addr) *addrs;
+      unsigned int cnt;
+
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
+	_dl_debug_printf ("\ncalling preinit: %s\n\n",
+			  DSO_FILENAME (main_map->l_name));
+
+      addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
+      for (cnt = 0; cnt < i; ++cnt)
+	((init_t) addrs[cnt]) (argc, argv, env);
+    }
+
+  /* Stupid users forced the ELF specification to be changed.  It now
+     says that the dynamic loader is responsible for determining the
+     order in which the constructors have to run.  The constructors
+     for all dependencies of an object must run before the constructor
+     for the object itself.  Circular dependencies are left unspecified.
+
+     This is highly questionable since it puts the burden on the dynamic
+     loader which has to find the dependencies at runtime instead of
+     letting the user do it right.  Stupidity rules!  */
+
+  i = main_map->l_searchlist.r_nlist;
+  while (i-- > 0)
+    call_init (main_map->l_initfini[i], argc, argv, env);
+
+#ifndef HAVE_INLINED_SYSCALLS
+  /* Finished starting up.  */
+  _dl_starting_up = 0;
+#endif
+}
diff --git a/REORG.TODO/elf/dl-iteratephdr.c b/REORG.TODO/elf/dl-iteratephdr.c
new file mode 100644
index 0000000000..ddd5bde831
--- /dev/null
+++ b/REORG.TODO/elf/dl-iteratephdr.c
@@ -0,0 +1,89 @@
+/* Get loaded objects program headers.
+   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <ldsodefs.h>
+#include <stddef.h>
+#include <libc-lock.h>
+
+static void
+cancel_handler (void *arg __attribute__((unused)))
+{
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+}
+
+hidden_proto (__dl_iterate_phdr)
+int
+__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+				    size_t size, void *data), void *data)
+{
+  struct link_map *l;
+  struct dl_phdr_info info;
+  int ret = 0;
+
+  /* Make sure nobody modifies the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+  __libc_cleanup_push (cancel_handler, NULL);
+
+  /* We have to determine the namespace of the caller since this determines
+     which namespace is reported.  */
+  size_t nloaded = GL(dl_ns)[0]._ns_nloaded;
+  Lmid_t ns = 0;
+#ifdef SHARED
+  const void *caller = RETURN_ADDRESS (0);
+  for (Lmid_t cnt = GL(dl_nns) - 1; cnt > 0; --cnt)
+    for (struct link_map *l = GL(dl_ns)[cnt]._ns_loaded; l; l = l->l_next)
+      {
+	/* We have to count the total number of loaded objects.  */
+	nloaded += GL(dl_ns)[cnt]._ns_nloaded;
+
+	if (caller >= (const void *) l->l_map_start
+	    && caller < (const void *) l->l_map_end
+	    && (l->l_contiguous
+		|| _dl_addr_inside_object (l, (ElfW(Addr)) caller)))
+	  ns = cnt;
+      }
+#endif
+
+  for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
+    {
+      info.dlpi_addr = l->l_real->l_addr;
+      info.dlpi_name = l->l_real->l_name;
+      info.dlpi_phdr = l->l_real->l_phdr;
+      info.dlpi_phnum = l->l_real->l_phnum;
+      info.dlpi_adds = GL(dl_load_adds);
+      info.dlpi_subs = GL(dl_load_adds) - nloaded;
+      info.dlpi_tls_data = NULL;
+      info.dlpi_tls_modid = l->l_real->l_tls_modid;
+      if (info.dlpi_tls_modid != 0)
+	info.dlpi_tls_data = GLRO(dl_tls_get_addr_soft) (l->l_real);
+      ret = callback (&info, sizeof (struct dl_phdr_info), data);
+      if (ret)
+	break;
+    }
+
+  /* Release the lock.  */
+  __libc_cleanup_pop (0);
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+
+  return ret;
+}
+hidden_def (__dl_iterate_phdr)
+
+weak_alias (__dl_iterate_phdr, dl_iterate_phdr);
diff --git a/REORG.TODO/elf/dl-libc.c b/REORG.TODO/elf/dl-libc.c
new file mode 100644
index 0000000000..9fdc8b1130
--- /dev/null
+++ b/REORG.TODO/elf/dl-libc.c
@@ -0,0 +1,330 @@
+/* Handle loading and unloading shared objects for internal libc purposes.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <ldsodefs.h>
+
+extern int __libc_argc attribute_hidden;
+extern char **__libc_argv attribute_hidden;
+
+extern char **__environ;
+
+/* The purpose of this file is to provide wrappers around the dynamic
+   linker error mechanism (similar to dlopen() et al in libdl) which
+   are usable from within libc.  Generally we want to throw away the
+   string that dlerror() would return and just pass back a null pointer
+   for errors.  This also lets the rest of libc not know about the error
+   handling mechanism.
+
+   Much of this code came from gconv_dl.c with slight modifications. */
+
+static int
+internal_function
+dlerror_run (void (*operate) (void *), void *args)
+{
+  const char *objname;
+  const char *last_errstring = NULL;
+  bool malloced;
+
+  int result = (_dl_catch_error (&objname, &last_errstring, &malloced,
+				operate, args)
+		?: last_errstring != NULL);
+
+  if (result && malloced)
+    free ((char *) last_errstring);
+
+  return result;
+}
+
+/* These functions are called by dlerror_run... */
+
+struct do_dlopen_args
+{
+  /* Argument to do_dlopen.  */
+  const char *name;
+  /* Opening mode.  */
+  int mode;
+  /* This is the caller of the dlopen() function.  */
+  const void *caller_dlopen;
+
+  /* Return from do_dlopen.  */
+  struct link_map *map;
+};
+
+struct do_dlsym_args
+{
+  /* Arguments to do_dlsym.  */
+  struct link_map *map;
+  const char *name;
+
+  /* Return values of do_dlsym.  */
+  lookup_t loadbase;
+  const ElfW(Sym) *ref;
+};
+
+static void
+do_dlopen (void *ptr)
+{
+  struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
+  /* Open and relocate the shared object.  */
+  args->map = GLRO(dl_open) (args->name, args->mode, args->caller_dlopen,
+			     __LM_ID_CALLER, __libc_argc, __libc_argv,
+			     __environ);
+}
+
+static void
+do_dlsym (void *ptr)
+{
+  struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
+  args->ref = NULL;
+  args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
+					     args->map->l_local_scope, NULL, 0,
+					     DL_LOOKUP_RETURN_NEWEST, NULL);
+}
+
+static void
+do_dlclose (void *ptr)
+{
+  GLRO(dl_close) ((struct link_map *) ptr);
+}
+
+/* This code is to support __libc_dlopen from __libc_dlopen'ed shared
+   libraries.  We need to ensure the statically linked __libc_dlopen
+   etc. functions are used instead of the dynamically loaded.  */
+struct dl_open_hook
+{
+  void *(*dlopen_mode) (const char *name, int mode);
+  void *(*dlsym) (void *map, const char *name);
+  int (*dlclose) (void *map);
+};
+
+#ifdef SHARED
+extern struct dl_open_hook *_dl_open_hook;
+libc_hidden_proto (_dl_open_hook);
+struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
+libc_hidden_data_def (_dl_open_hook);
+#else
+static void
+do_dlsym_private (void *ptr)
+{
+  lookup_t l;
+  struct r_found_version vers;
+  vers.name = "GLIBC_PRIVATE";
+  vers.hidden = 1;
+  /* vers.hash = _dl_elf_hash (vers.name);  */
+  vers.hash = 0x0963cf85;
+  vers.filename = NULL;
+
+  struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
+  args->ref = NULL;
+  l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
+				args->map->l_scope, &vers, 0, 0, NULL);
+  args->loadbase = l;
+}
+
+static struct dl_open_hook _dl_open_hook =
+  {
+    .dlopen_mode = __libc_dlopen_mode,
+    .dlsym = __libc_dlsym,
+    .dlclose = __libc_dlclose
+  };
+#endif
+
+/* ... and these functions call dlerror_run. */
+
+void *
+__libc_dlopen_mode (const char *name, int mode)
+{
+  struct do_dlopen_args args;
+  args.name = name;
+  args.mode = mode;
+  args.caller_dlopen = RETURN_ADDRESS (0);
+
+#ifdef SHARED
+  if (__glibc_unlikely (_dl_open_hook != NULL))
+    return _dl_open_hook->dlopen_mode (name, mode);
+  return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
+#else
+  if (dlerror_run (do_dlopen, &args))
+    return NULL;
+
+  __libc_register_dl_open_hook (args.map);
+  __libc_register_dlfcn_hook (args.map);
+  return (void *) args.map;
+#endif
+}
+libc_hidden_def (__libc_dlopen_mode)
+
+#ifndef SHARED
+void *
+__libc_dlsym_private (struct link_map *map, const char *name)
+{
+  struct do_dlsym_args sargs;
+  sargs.map = map;
+  sargs.name = name;
+
+  if (! dlerror_run (do_dlsym_private, &sargs))
+    return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref);
+  return NULL;
+}
+
+void
+__libc_register_dl_open_hook (struct link_map *map)
+{
+  struct dl_open_hook **hook;
+
+  hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook");
+  if (hook != NULL)
+    *hook = &_dl_open_hook;
+}
+#endif
+
+void *
+__libc_dlsym (void *map, const char *name)
+{
+  struct do_dlsym_args args;
+  args.map = map;
+  args.name = name;
+
+#ifdef SHARED
+  if (__glibc_unlikely (_dl_open_hook != NULL))
+    return _dl_open_hook->dlsym (map, name);
+#endif
+  return (dlerror_run (do_dlsym, &args) ? NULL
+	  : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
+}
+libc_hidden_def (__libc_dlsym)
+
+int
+__libc_dlclose (void *map)
+{
+#ifdef SHARED
+  if (__glibc_unlikely (_dl_open_hook != NULL))
+    return _dl_open_hook->dlclose (map);
+#endif
+  return dlerror_run (do_dlclose, map);
+}
+libc_hidden_def (__libc_dlclose)
+
+
+static bool __libc_freeres_fn_section
+free_slotinfo (struct dtv_slotinfo_list **elemp)
+{
+  size_t cnt;
+
+  if (*elemp == NULL)
+    /* Nothing here, all is removed (or there never was anything).  */
+    return true;
+
+  if (!free_slotinfo (&(*elemp)->next))
+    /* We cannot free the entry.  */
+    return false;
+
+  /* That cleared our next pointer for us.  */
+
+  for (cnt = 0; cnt < (*elemp)->len; ++cnt)
+    if ((*elemp)->slotinfo[cnt].map != NULL)
+      /* Still used.  */
+      return false;
+
+  /* We can remove the list element.  */
+  free (*elemp);
+  *elemp = NULL;
+
+  return true;
+}
+
+
+libc_freeres_fn (free_mem)
+{
+  struct link_map *l;
+  struct r_search_path_elem *d;
+
+  /* Remove all search directories.  */
+  d = GL(dl_all_dirs);
+  while (d != GLRO(dl_init_all_dirs))
+    {
+      struct r_search_path_elem *old = d;
+      d = d->next;
+      free (old);
+    }
+
+  for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
+    {
+      for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
+	{
+	  struct libname_list *lnp = l->l_libname->next;
+
+	  l->l_libname->next = NULL;
+
+	  /* Remove all additional names added to the objects.  */
+	  while (lnp != NULL)
+	    {
+	      struct libname_list *old = lnp;
+	      lnp = lnp->next;
+	      if (! old->dont_free)
+		free (old);
+	    }
+
+	  /* Free the initfini dependency list.  */
+	  if (l->l_free_initfini)
+	    free (l->l_initfini);
+	  l->l_initfini = NULL;
+	}
+
+      if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
+	  && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
+	      // XXX Check whether we need NS-specific initial_searchlist
+	      == GLRO(dl_initial_searchlist).r_nlist))
+	{
+	  /* All object dynamically loaded by the program are unloaded.  Free
+	     the memory allocated for the global scope variable.  */
+	  struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
+
+	  /* Put the old map in.  */
+	  GL(dl_ns)[ns]._ns_main_searchlist->r_list
+	    // XXX Check whether we need NS-specific initial_searchlist
+	    = GLRO(dl_initial_searchlist).r_list;
+	  /* Signal that the original map is used.  */
+	  GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
+
+	  /* Now free the old map.  */
+	  free (old);
+	}
+    }
+
+  /* Free the memory allocated for the dtv slotinfo array.  We can do
+     this only if all modules which used this memory are unloaded.  */
+#ifdef SHARED
+  if (GL(dl_initial_dtv) == NULL)
+    /* There was no initial TLS setup, it was set up later when
+       it used the normal malloc.  */
+    free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
+  else
+#endif
+    /* The first element of the list does not have to be deallocated.
+       It was allocated in the dynamic linker (i.e., with a different
+       malloc), and in the static library it's in .bss space.  */
+    free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
+
+  void *scope_free_list = GL(dl_scope_free_list);
+  GL(dl_scope_free_list) = NULL;
+  free (scope_free_list);
+}
diff --git a/REORG.TODO/elf/dl-load.c b/REORG.TODO/elf/dl-load.c
new file mode 100644
index 0000000000..c1b6d4ba0f
--- /dev/null
+++ b/REORG.TODO/elf/dl-load.c
@@ -0,0 +1,2307 @@
+/* Map in a shared object's segments from the file.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <bits/wordsize.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "dynamic-link.h"
+#include <abi-tag.h>
+#include <stackinfo.h>
+#include <caller.h>
+#include <sysdep.h>
+#include <stap-probe.h>
+#include <libc-pointer-arith.h>
+
+#include <dl-dst.h>
+#include <dl-load.h>
+#include <dl-map-segments.h>
+#include <dl-unmap-segments.h>
+#include <dl-machine-reject-phdr.h>
+#include <dl-sysdep-open.h>
+
+
+#include <endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+# define byteorder ELFDATA2MSB
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# define byteorder ELFDATA2LSB
+#else
+# error "Unknown BYTE_ORDER " BYTE_ORDER
+# define byteorder ELFDATANONE
+#endif
+
+#define STRING(x) __STRING (x)
+
+
+int __stack_prot attribute_hidden attribute_relro
+#if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN
+  = PROT_GROWSDOWN;
+#elif _STACK_GROWS_UP && defined PROT_GROWSUP
+  = PROT_GROWSUP;
+#else
+  = 0;
+#endif
+
+
+/* Type for the buffer we put the ELF header and hopefully the program
+   header.  This buffer does not really have to be too large.  In most
+   cases the program header follows the ELF header directly.  If this
+   is not the case all bets are off and we can make the header
+   arbitrarily large and still won't get it read.  This means the only
+   question is how large are the ELF and program header combined.  The
+   ELF header 32-bit files is 52 bytes long and in 64-bit files is 64
+   bytes long.  Each program header entry is again 32 and 56 bytes
+   long respectively.  I.e., even with a file which has 10 program
+   header entries we only have to read 372B/624B respectively.  Add to
+   this a bit of margin for program notes and reading 512B and 832B
+   for 32-bit and 64-bit files respecitvely is enough.  If this
+   heuristic should really fail for some file the code in
+   `_dl_map_object_from_fd' knows how to recover.  */
+struct filebuf
+{
+  ssize_t len;
+#if __WORDSIZE == 32
+# define FILEBUF_SIZE 512
+#else
+# define FILEBUF_SIZE 832
+#endif
+  char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr)))));
+};
+
+/* This is the decomposed LD_LIBRARY_PATH search path.  */
+static struct r_search_path_struct env_path_list attribute_relro;
+
+/* List of the hardware capabilities we might end up using.  */
+static const struct r_strlenpair *capstr attribute_relro;
+static size_t ncapstr attribute_relro;
+static size_t max_capstrlen attribute_relro;
+
+
+/* Get the generated information about the trusted directories.  */
+#include "trusted-dirs.h"
+
+static const char system_dirs[] = SYSTEM_DIRS;
+static const size_t system_dirs_len[] =
+{
+  SYSTEM_DIRS_LEN
+};
+#define nsystem_dirs_len \
+  (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
+
+
+static bool
+is_trusted_path (const char *path, size_t len)
+{
+  const char *trun = system_dirs;
+
+  for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
+    {
+      if (len == system_dirs_len[idx] && memcmp (trun, path, len) == 0)
+	/* Found it.  */
+	return true;
+
+      trun += system_dirs_len[idx] + 1;
+    }
+
+  return false;
+}
+
+
+static bool
+is_trusted_path_normalize (const char *path, size_t len)
+{
+  if (len == 0)
+    return false;
+
+  if (*path == ':')
+    {
+      ++path;
+      --len;
+    }
+
+  char *npath = (char *) alloca (len + 2);
+  char *wnp = npath;
+  while (*path != '\0')
+    {
+      if (path[0] == '/')
+	{
+	  if (path[1] == '.')
+	    {
+	      if (path[2] == '.' && (path[3] == '/' || path[3] == '\0'))
+		{
+		  while (wnp > npath && *--wnp != '/')
+		    ;
+		  path += 3;
+		  continue;
+		}
+	      else if (path[2] == '/' || path[2] == '\0')
+		{
+		  path += 2;
+		  continue;
+		}
+	    }
+
+	  if (wnp > npath && wnp[-1] == '/')
+	    {
+	      ++path;
+	      continue;
+	    }
+	}
+
+      *wnp++ = *path++;
+    }
+
+  if (wnp == npath || wnp[-1] != '/')
+    *wnp++ = '/';
+
+  const char *trun = system_dirs;
+
+  for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
+    {
+      if (wnp - npath >= system_dirs_len[idx]
+	  && memcmp (trun, npath, system_dirs_len[idx]) == 0)
+	/* Found it.  */
+	return true;
+
+      trun += system_dirs_len[idx] + 1;
+    }
+
+  return false;
+}
+
+
+static size_t
+is_dst (const char *start, const char *name, const char *str,
+	int is_path, int secure)
+{
+  size_t len;
+  bool is_curly = false;
+
+  if (name[0] == '{')
+    {
+      is_curly = true;
+      ++name;
+    }
+
+  len = 0;
+  while (name[len] == str[len] && name[len] != '\0')
+    ++len;
+
+  if (is_curly)
+    {
+      if (name[len] != '}')
+	return 0;
+
+      /* Point again at the beginning of the name.  */
+      --name;
+      /* Skip over closing curly brace and adjust for the --name.  */
+      len += 2;
+    }
+  else if (name[len] != '\0' && name[len] != '/'
+	   && (!is_path || name[len] != ':'))
+    return 0;
+
+  if (__glibc_unlikely (secure)
+      && ((name[len] != '\0' && name[len] != '/'
+	   && (!is_path || name[len] != ':'))
+	  || (name != start + 1 && (!is_path || name[-2] != ':'))))
+    return 0;
+
+  return len;
+}
+
+
+size_t
+_dl_dst_count (const char *name, int is_path)
+{
+  const char *const start = name;
+  size_t cnt = 0;
+
+  do
+    {
+      size_t len;
+
+      /* $ORIGIN is not expanded for SUID/GUID programs (except if it
+	 is $ORIGIN alone) and it must always appear first in path.  */
+      ++name;
+      if ((len = is_dst (start, name, "ORIGIN", is_path,
+			 __libc_enable_secure)) != 0
+	  || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
+	  || (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
+	++cnt;
+
+      name = strchr (name + len, '$');
+    }
+  while (name != NULL);
+
+  return cnt;
+}
+
+
+char *
+_dl_dst_substitute (struct link_map *l, const char *name, char *result,
+		    int is_path)
+{
+  const char *const start = name;
+
+  /* Now fill the result path.  While copying over the string we keep
+     track of the start of the last path element.  When we come across
+     a DST we copy over the value or (if the value is not available)
+     leave the entire path element out.  */
+  char *wp = result;
+  char *last_elem = result;
+  bool check_for_trusted = false;
+
+  do
+    {
+      if (__glibc_unlikely (*name == '$'))
+	{
+	  const char *repl = NULL;
+	  size_t len;
+
+	  ++name;
+	  if ((len = is_dst (start, name, "ORIGIN", is_path,
+			     __libc_enable_secure)) != 0)
+	    {
+	      repl = l->l_origin;
+	      check_for_trusted = (__libc_enable_secure
+				   && l->l_type == lt_executable);
+	    }
+	  else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
+	    repl = GLRO(dl_platform);
+	  else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
+	    repl = DL_DST_LIB;
+
+	  if (repl != NULL && repl != (const char *) -1)
+	    {
+	      wp = __stpcpy (wp, repl);
+	      name += len;
+	    }
+	  else if (len > 1)
+	    {
+	      /* We cannot use this path element, the value of the
+		 replacement is unknown.  */
+	      wp = last_elem;
+	      name += len;
+	      while (*name != '\0' && (!is_path || *name != ':'))
+		++name;
+	      /* Also skip following colon if this is the first rpath
+		 element, but keep an empty element at the end.  */
+	      if (wp == result && is_path && *name == ':' && name[1] != '\0')
+		++name;
+	    }
+	  else
+	    /* No DST we recognize.  */
+	    *wp++ = '$';
+	}
+      else
+	{
+	  *wp++ = *name++;
+	  if (is_path && *name == ':')
+	    {
+	      /* In SUID/SGID programs, after $ORIGIN expansion the
+		 normalized path must be rooted in one of the trusted
+		 directories.  */
+	      if (__glibc_unlikely (check_for_trusted)
+		  && !is_trusted_path_normalize (last_elem, wp - last_elem))
+		wp = last_elem;
+	      else
+		last_elem = wp;
+
+	      check_for_trusted = false;
+	    }
+	}
+    }
+  while (*name != '\0');
+
+  /* In SUID/SGID programs, after $ORIGIN expansion the normalized
+     path must be rooted in one of the trusted directories.  */
+  if (__glibc_unlikely (check_for_trusted)
+      && !is_trusted_path_normalize (last_elem, wp - last_elem))
+    wp = last_elem;
+
+  *wp = '\0';
+
+  return result;
+}
+
+
+/* Return copy of argument with all recognized dynamic string tokens
+   ($ORIGIN and $PLATFORM for now) replaced.  On some platforms it
+   might not be possible to determine the path from which the object
+   belonging to the map is loaded.  In this case the path element
+   containing $ORIGIN is left out.  */
+static char *
+expand_dynamic_string_token (struct link_map *l, const char *s, int is_path)
+{
+  /* We make two runs over the string.  First we determine how large the
+     resulting string is and then we copy it over.  Since this is no
+     frequently executed operation we are looking here not for performance
+     but rather for code size.  */
+  size_t cnt;
+  size_t total;
+  char *result;
+
+  /* Determine the number of DST elements.  */
+  cnt = DL_DST_COUNT (s, is_path);
+
+  /* If we do not have to replace anything simply copy the string.  */
+  if (__glibc_likely (cnt == 0))
+    return __strdup (s);
+
+  /* Determine the length of the substituted string.  */
+  total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
+
+  /* Allocate the necessary memory.  */
+  result = (char *) malloc (total + 1);
+  if (result == NULL)
+    return NULL;
+
+  return _dl_dst_substitute (l, s, result, is_path);
+}
+
+
+/* Add `name' to the list of names for a particular shared object.
+   `name' is expected to have been allocated with malloc and will
+   be freed if the shared object already has this name.
+   Returns false if the object already had this name.  */
+static void
+internal_function
+add_name_to_object (struct link_map *l, const char *name)
+{
+  struct libname_list *lnp, *lastp;
+  struct libname_list *newname;
+  size_t name_len;
+
+  lastp = NULL;
+  for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next)
+    if (strcmp (name, lnp->name) == 0)
+      return;
+
+  name_len = strlen (name) + 1;
+  newname = (struct libname_list *) malloc (sizeof *newname + name_len);
+  if (newname == NULL)
+    {
+      /* No more memory.  */
+      _dl_signal_error (ENOMEM, name, NULL, N_("cannot allocate name record"));
+      return;
+    }
+  /* The object should have a libname set from _dl_new_object.  */
+  assert (lastp != NULL);
+
+  newname->name = memcpy (newname + 1, name, name_len);
+  newname->next = NULL;
+  newname->dont_free = 0;
+  lastp->next = newname;
+}
+
+/* Standard search directories.  */
+static struct r_search_path_struct rtld_search_dirs attribute_relro;
+
+static size_t max_dirnamelen;
+
+static struct r_search_path_elem **
+fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
+	      int check_trusted, const char *what, const char *where,
+	      struct link_map *l)
+{
+  char *cp;
+  size_t nelems = 0;
+  char *to_free;
+
+  while ((cp = __strsep (&rpath, sep)) != NULL)
+    {
+      struct r_search_path_elem *dirp;
+
+      to_free = cp = expand_dynamic_string_token (l, cp, 1);
+
+      size_t len = strlen (cp);
+
+      /* `strsep' can pass an empty string.  This has to be
+	 interpreted as `use the current directory'. */
+      if (len == 0)
+	{
+	  static const char curwd[] = "./";
+	  cp = (char *) curwd;
+	}
+
+      /* Remove trailing slashes (except for "/").  */
+      while (len > 1 && cp[len - 1] == '/')
+	--len;
+
+      /* Now add one if there is none so far.  */
+      if (len > 0 && cp[len - 1] != '/')
+	cp[len++] = '/';
+
+      /* Make sure we don't use untrusted directories if we run SUID.  */
+      if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
+	{
+	  free (to_free);
+	  continue;
+	}
+
+      /* See if this directory is already known.  */
+      for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next)
+	if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
+	  break;
+
+      if (dirp != NULL)
+	{
+	  /* It is available, see whether it's on our own list.  */
+	  size_t cnt;
+	  for (cnt = 0; cnt < nelems; ++cnt)
+	    if (result[cnt] == dirp)
+	      break;
+
+	  if (cnt == nelems)
+	    result[nelems++] = dirp;
+	}
+      else
+	{
+	  size_t cnt;
+	  enum r_dir_status init_val;
+	  size_t where_len = where ? strlen (where) + 1 : 0;
+
+	  /* It's a new directory.  Create an entry and add it.  */
+	  dirp = (struct r_search_path_elem *)
+	    malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status)
+		    + where_len + len + 1);
+	  if (dirp == NULL)
+	    _dl_signal_error (ENOMEM, NULL, NULL,
+			      N_("cannot create cache for search path"));
+
+	  dirp->dirname = ((char *) dirp + sizeof (*dirp)
+			   + ncapstr * sizeof (enum r_dir_status));
+	  *((char *) __mempcpy ((char *) dirp->dirname, cp, len)) = '\0';
+	  dirp->dirnamelen = len;
+
+	  if (len > max_dirnamelen)
+	    max_dirnamelen = len;
+
+	  /* We have to make sure all the relative directories are
+	     never ignored.  The current directory might change and
+	     all our saved information would be void.  */
+	  init_val = cp[0] != '/' ? existing : unknown;
+	  for (cnt = 0; cnt < ncapstr; ++cnt)
+	    dirp->status[cnt] = init_val;
+
+	  dirp->what = what;
+	  if (__glibc_likely (where != NULL))
+	    dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1
+				  + (ncapstr * sizeof (enum r_dir_status)),
+				  where, where_len);
+	  else
+	    dirp->where = NULL;
+
+	  dirp->next = GL(dl_all_dirs);
+	  GL(dl_all_dirs) = dirp;
+
+	  /* Put it in the result array.  */
+	  result[nelems++] = dirp;
+	}
+      free (to_free);
+    }
+
+  /* Terminate the array.  */
+  result[nelems] = NULL;
+
+  return result;
+}
+
+
+static bool
+internal_function
+decompose_rpath (struct r_search_path_struct *sps,
+		 const char *rpath, struct link_map *l, const char *what)
+{
+  /* Make a copy we can work with.  */
+  const char *where = l->l_name;
+  char *copy;
+  char *cp;
+  struct r_search_path_elem **result;
+  size_t nelems;
+  /* Initialize to please the compiler.  */
+  const char *errstring = NULL;
+
+  /* First see whether we must forget the RUNPATH and RPATH from this
+     object.  */
+  if (__glibc_unlikely (GLRO(dl_inhibit_rpath) != NULL)
+      && !__libc_enable_secure)
+    {
+      const char *inhp = GLRO(dl_inhibit_rpath);
+
+      do
+	{
+	  const char *wp = where;
+
+	  while (*inhp == *wp && *wp != '\0')
+	    {
+	      ++inhp;
+	      ++wp;
+	    }
+
+	  if (*wp == '\0' && (*inhp == '\0' || *inhp == ':'))
+	    {
+	      /* This object is on the list of objects for which the
+		 RUNPATH and RPATH must not be used.  */
+	      sps->dirs = (void *) -1;
+	      return false;
+	    }
+
+	  while (*inhp != '\0')
+	    if (*inhp++ == ':')
+	      break;
+	}
+      while (*inhp != '\0');
+    }
+
+  /* Make a writable copy.  */
+  copy = __strdup (rpath);
+  if (copy == NULL)
+    {
+      errstring = N_("cannot create RUNPATH/RPATH copy");
+      goto signal_error;
+    }
+
+  /* Ignore empty rpaths.  */
+  if (*copy == 0)
+    {
+      free (copy);
+      sps->dirs = (struct r_search_path_elem **) -1;
+      return false;
+    }
+
+  /* Count the number of necessary elements in the result array.  */
+  nelems = 0;
+  for (cp = copy; *cp != '\0'; ++cp)
+    if (*cp == ':')
+      ++nelems;
+
+  /* Allocate room for the result.  NELEMS + 1 is an upper limit for the
+     number of necessary entries.  */
+  result = (struct r_search_path_elem **) malloc ((nelems + 1 + 1)
+						  * sizeof (*result));
+  if (result == NULL)
+    {
+      free (copy);
+      errstring = N_("cannot create cache for search path");
+    signal_error:
+      _dl_signal_error (ENOMEM, NULL, NULL, errstring);
+    }
+
+  fillin_rpath (copy, result, ":", 0, what, where, l);
+
+  /* Free the copied RPATH string.  `fillin_rpath' make own copies if
+     necessary.  */
+  free (copy);
+
+  sps->dirs = result;
+  /* The caller will change this value if we haven't used a real malloc.  */
+  sps->malloced = 1;
+  return true;
+}
+
+/* Make sure cached path information is stored in *SP
+   and return true if there are any paths to search there.  */
+static bool
+cache_rpath (struct link_map *l,
+	     struct r_search_path_struct *sp,
+	     int tag,
+	     const char *what)
+{
+  if (sp->dirs == (void *) -1)
+    return false;
+
+  if (sp->dirs != NULL)
+    return true;
+
+  if (l->l_info[tag] == NULL)
+    {
+      /* There is no path.  */
+      sp->dirs = (void *) -1;
+      return false;
+    }
+
+  /* Make sure the cache information is available.  */
+  return decompose_rpath (sp, (const char *) (D_PTR (l, l_info[DT_STRTAB])
+					      + l->l_info[tag]->d_un.d_val),
+			  l, what);
+}
+
+
+void
+internal_function
+_dl_init_paths (const char *llp)
+{
+  size_t idx;
+  const char *strp;
+  struct r_search_path_elem *pelem, **aelem;
+  size_t round_size;
+  struct link_map __attribute__ ((unused)) *l = NULL;
+  /* Initialize to please the compiler.  */
+  const char *errstring = NULL;
+
+  /* Fill in the information about the application's RPATH and the
+     directories addressed by the LD_LIBRARY_PATH environment variable.  */
+
+  /* Get the capabilities.  */
+  capstr = _dl_important_hwcaps (GLRO(dl_platform), GLRO(dl_platformlen),
+				 &ncapstr, &max_capstrlen);
+
+  /* First set up the rest of the default search directory entries.  */
+  aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **)
+    malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *));
+  if (rtld_search_dirs.dirs == NULL)
+    {
+      errstring = N_("cannot create search path array");
+    signal_error:
+      _dl_signal_error (ENOMEM, NULL, NULL, errstring);
+    }
+
+  round_size = ((2 * sizeof (struct r_search_path_elem) - 1
+		 + ncapstr * sizeof (enum r_dir_status))
+		/ sizeof (struct r_search_path_elem));
+
+  rtld_search_dirs.dirs[0] = (struct r_search_path_elem *)
+    malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]))
+	    * round_size * sizeof (struct r_search_path_elem));
+  if (rtld_search_dirs.dirs[0] == NULL)
+    {
+      errstring = N_("cannot create cache for search path");
+      goto signal_error;
+    }
+
+  rtld_search_dirs.malloced = 0;
+  pelem = GL(dl_all_dirs) = rtld_search_dirs.dirs[0];
+  strp = system_dirs;
+  idx = 0;
+
+  do
+    {
+      size_t cnt;
+
+      *aelem++ = pelem;
+
+      pelem->what = "system search path";
+      pelem->where = NULL;
+
+      pelem->dirname = strp;
+      pelem->dirnamelen = system_dirs_len[idx];
+      strp += system_dirs_len[idx] + 1;
+
+      /* System paths must be absolute.  */
+      assert (pelem->dirname[0] == '/');
+      for (cnt = 0; cnt < ncapstr; ++cnt)
+	pelem->status[cnt] = unknown;
+
+      pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size));
+
+      pelem += round_size;
+    }
+  while (idx < nsystem_dirs_len);
+
+  max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
+  *aelem = NULL;
+
+#ifdef SHARED
+  /* This points to the map of the main object.  */
+  l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+  if (l != NULL)
+    {
+      assert (l->l_type != lt_loaded);
+
+      if (l->l_info[DT_RUNPATH])
+	{
+	  /* Allocate room for the search path and fill in information
+	     from RUNPATH.  */
+	  decompose_rpath (&l->l_runpath_dirs,
+			   (const void *) (D_PTR (l, l_info[DT_STRTAB])
+					   + l->l_info[DT_RUNPATH]->d_un.d_val),
+			   l, "RUNPATH");
+	  /* During rtld init the memory is allocated by the stub malloc,
+	     prevent any attempt to free it by the normal malloc.  */
+	  l->l_runpath_dirs.malloced = 0;
+
+	  /* The RPATH is ignored.  */
+	  l->l_rpath_dirs.dirs = (void *) -1;
+	}
+      else
+	{
+	  l->l_runpath_dirs.dirs = (void *) -1;
+
+	  if (l->l_info[DT_RPATH])
+	    {
+	      /* Allocate room for the search path and fill in information
+		 from RPATH.  */
+	      decompose_rpath (&l->l_rpath_dirs,
+			       (const void *) (D_PTR (l, l_info[DT_STRTAB])
+					       + l->l_info[DT_RPATH]->d_un.d_val),
+			       l, "RPATH");
+	      /* During rtld init the memory is allocated by the stub
+		 malloc, prevent any attempt to free it by the normal
+		 malloc.  */
+	      l->l_rpath_dirs.malloced = 0;
+	    }
+	  else
+	    l->l_rpath_dirs.dirs = (void *) -1;
+	}
+    }
+#endif	/* SHARED */
+
+  if (llp != NULL && *llp != '\0')
+    {
+      size_t nllp;
+      const char *cp = llp;
+      char *llp_tmp;
+
+#ifdef SHARED
+      /* Expand DSTs.  */
+      size_t cnt = DL_DST_COUNT (llp, 1);
+      if (__glibc_likely (cnt == 0))
+	llp_tmp = strdupa (llp);
+      else
+	{
+	  /* Determine the length of the substituted string.  */
+	  size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
+
+	  /* Allocate the necessary memory.  */
+	  llp_tmp = (char *) alloca (total + 1);
+	  llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
+	}
+#else
+      llp_tmp = strdupa (llp);
+#endif
+
+      /* Decompose the LD_LIBRARY_PATH contents.  First determine how many
+	 elements it has.  */
+      nllp = 1;
+      while (*cp)
+	{
+	  if (*cp == ':' || *cp == ';')
+	    ++nllp;
+	  ++cp;
+	}
+
+      env_path_list.dirs = (struct r_search_path_elem **)
+	malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));
+      if (env_path_list.dirs == NULL)
+	{
+	  errstring = N_("cannot create cache for search path");
+	  goto signal_error;
+	}
+
+      (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;",
+			   __libc_enable_secure, "LD_LIBRARY_PATH",
+			   NULL, l);
+
+      if (env_path_list.dirs[0] == NULL)
+	{
+	  free (env_path_list.dirs);
+	  env_path_list.dirs = (void *) -1;
+	}
+
+      env_path_list.malloced = 0;
+    }
+  else
+    env_path_list.dirs = (void *) -1;
+}
+
+
+static void
+__attribute__ ((noreturn, noinline))
+lose (int code, int fd, const char *name, char *realname, struct link_map *l,
+      const char *msg, struct r_debug *r, Lmid_t nsid)
+{
+  /* The file might already be closed.  */
+  if (fd != -1)
+    (void) __close (fd);
+  if (l != NULL && l->l_origin != (char *) -1l)
+    free ((char *) l->l_origin);
+  free (l);
+  free (realname);
+
+  if (r != NULL)
+    {
+      r->r_state = RT_CONSISTENT;
+      _dl_debug_state ();
+      LIBC_PROBE (map_failed, 2, nsid, r);
+    }
+
+  _dl_signal_error (code, name, NULL, msg);
+}
+
+
+/* Map in the shared object NAME, actually located in REALNAME, and already
+   opened on FD.  */
+
+#ifndef EXTERNAL_MAP_FROM_FD
+static
+#endif
+struct link_map *
+_dl_map_object_from_fd (const char *name, const char *origname, int fd,
+			struct filebuf *fbp, char *realname,
+			struct link_map *loader, int l_type, int mode,
+			void **stack_endp, Lmid_t nsid)
+{
+  struct link_map *l = NULL;
+  const ElfW(Ehdr) *header;
+  const ElfW(Phdr) *phdr;
+  const ElfW(Phdr) *ph;
+  size_t maplength;
+  int type;
+  /* Initialize to keep the compiler happy.  */
+  const char *errstring = NULL;
+  int errval = 0;
+  struct r_debug *r = _dl_debug_initialize (0, nsid);
+  bool make_consistent = false;
+
+  /* Get file information.  */
+  struct r_file_id id;
+  if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
+    {
+      errstring = N_("cannot stat shared object");
+    call_lose_errno:
+      errval = errno;
+    call_lose:
+      lose (errval, fd, name, realname, l, errstring,
+	    make_consistent ? r : NULL, nsid);
+    }
+
+  /* Look again to see if the real name matched another already loaded.  */
+  for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+    if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
+      {
+	/* The object is already loaded.
+	   Just bump its reference count and return it.  */
+	__close (fd);
+
+	/* If the name is not in the list of names for this object add
+	   it.  */
+	free (realname);
+	add_name_to_object (l, name);
+
+	return l;
+      }
+
+#ifdef SHARED
+  /* When loading into a namespace other than the base one we must
+     avoid loading ld.so since there can only be one copy.  Ever.  */
+  if (__glibc_unlikely (nsid != LM_ID_BASE)
+      && (_dl_file_id_match_p (&id, &GL(dl_rtld_map).l_file_id)
+	  || _dl_name_match_p (name, &GL(dl_rtld_map))))
+    {
+      /* This is indeed ld.so.  Create a new link_map which refers to
+	 the real one for almost everything.  */
+      l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
+      if (l == NULL)
+	goto fail_new;
+
+      /* Refer to the real descriptor.  */
+      l->l_real = &GL(dl_rtld_map);
+
+      /* No need to bump the refcount of the real object, ld.so will
+	 never be unloaded.  */
+      __close (fd);
+
+      /* Add the map for the mirrored object to the object list.  */
+      _dl_add_to_namespace_list (l, nsid);
+
+      return l;
+    }
+#endif
+
+  if (mode & RTLD_NOLOAD)
+    {
+      /* We are not supposed to load the object unless it is already
+	 loaded.  So return now.  */
+      free (realname);
+      __close (fd);
+      return NULL;
+    }
+
+  /* Print debugging message.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+    _dl_debug_printf ("file=%s [%lu];  generating link map\n", name, nsid);
+
+  /* This is the ELF header.  We read it in `open_verify'.  */
+  header = (void *) fbp->buf;
+
+#ifndef MAP_ANON
+# define MAP_ANON 0
+  if (_dl_zerofd == -1)
+    {
+      _dl_zerofd = _dl_sysdep_open_zero_fill ();
+      if (_dl_zerofd == -1)
+	{
+	  free (realname);
+	  __close (fd);
+	  _dl_signal_error (errno, NULL, NULL,
+			    N_("cannot open zero fill device"));
+	}
+    }
+#endif
+
+  /* Signal that we are going to add new objects.  */
+  if (r->r_state == RT_CONSISTENT)
+    {
+#ifdef SHARED
+      /* Auditing checkpoint: we are going to add new objects.  */
+      if ((mode & __RTLD_AUDIT) == 0
+	  && __glibc_unlikely (GLRO(dl_naudit) > 0))
+	{
+	  struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
+	  /* Do not call the functions for any auditing object.  */
+	  if (head->l_auditing == 0)
+	    {
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  if (afct->activity != NULL)
+		    afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD);
+
+		  afct = afct->next;
+		}
+	    }
+	}
+#endif
+
+      /* Notify the debugger we have added some objects.  We need to
+	 call _dl_debug_initialize in a static program in case dynamic
+	 linking has not been used before.  */
+      r->r_state = RT_ADD;
+      _dl_debug_state ();
+      LIBC_PROBE (map_start, 2, nsid, r);
+      make_consistent = true;
+    }
+  else
+    assert (r->r_state == RT_ADD);
+
+  /* Enter the new object in the list of loaded objects.  */
+  l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
+  if (__glibc_unlikely (l == NULL))
+    {
+#ifdef SHARED
+    fail_new:
+#endif
+      errstring = N_("cannot create shared object descriptor");
+      goto call_lose_errno;
+    }
+
+  /* Extract the remaining details we need from the ELF header
+     and then read in the program header table.  */
+  l->l_entry = header->e_entry;
+  type = header->e_type;
+  l->l_phnum = header->e_phnum;
+
+  maplength = header->e_phnum * sizeof (ElfW(Phdr));
+  if (header->e_phoff + maplength <= (size_t) fbp->len)
+    phdr = (void *) (fbp->buf + header->e_phoff);
+  else
+    {
+      phdr = alloca (maplength);
+      __lseek (fd, header->e_phoff, SEEK_SET);
+      if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
+	{
+	  errstring = N_("cannot read file data");
+	  goto call_lose_errno;
+	}
+    }
+
+   /* On most platforms presume that PT_GNU_STACK is absent and the stack is
+    * executable.  Other platforms default to a nonexecutable stack and don't
+    * need PT_GNU_STACK to do so.  */
+   uint_fast16_t stack_flags = DEFAULT_STACK_PERMS;
+
+  {
+    /* Scan the program header table, collecting its load commands.  */
+    struct loadcmd loadcmds[l->l_phnum];
+    size_t nloadcmds = 0;
+    bool has_holes = false;
+
+    /* The struct is initialized to zero so this is not necessary:
+    l->l_ld = 0;
+    l->l_phdr = 0;
+    l->l_addr = 0; */
+    for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
+      switch (ph->p_type)
+	{
+	  /* These entries tell us where to find things once the file's
+	     segments are mapped in.  We record the addresses it says
+	     verbatim, and later correct for the run-time load address.  */
+	case PT_DYNAMIC:
+	  l->l_ld = (void *) ph->p_vaddr;
+	  l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+	  break;
+
+	case PT_PHDR:
+	  l->l_phdr = (void *) ph->p_vaddr;
+	  break;
+
+	case PT_LOAD:
+	  /* A load command tells us to map in part of the file.
+	     We record the load commands and process them all later.  */
+	  if (__glibc_unlikely ((ph->p_align & (GLRO(dl_pagesize) - 1)) != 0))
+	    {
+	      errstring = N_("ELF load command alignment not page-aligned");
+	      goto call_lose;
+	    }
+	  if (__glibc_unlikely (((ph->p_vaddr - ph->p_offset)
+				 & (ph->p_align - 1)) != 0))
+	    {
+	      errstring
+		= N_("ELF load command address/offset not properly aligned");
+	      goto call_lose;
+	    }
+
+	  struct loadcmd *c = &loadcmds[nloadcmds++];
+	  c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
+	  c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
+	  c->dataend = ph->p_vaddr + ph->p_filesz;
+	  c->allocend = ph->p_vaddr + ph->p_memsz;
+	  c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
+
+	  /* Determine whether there is a gap between the last segment
+	     and this one.  */
+	  if (nloadcmds > 1 && c[-1].mapend != c->mapstart)
+	    has_holes = true;
+
+	  /* Optimize a common case.  */
+#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
+	  c->prot = (PF_TO_PROT
+		     >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
+#else
+	  c->prot = 0;
+	  if (ph->p_flags & PF_R)
+	    c->prot |= PROT_READ;
+	  if (ph->p_flags & PF_W)
+	    c->prot |= PROT_WRITE;
+	  if (ph->p_flags & PF_X)
+	    c->prot |= PROT_EXEC;
+#endif
+	  break;
+
+	case PT_TLS:
+	  if (ph->p_memsz == 0)
+	    /* Nothing to do for an empty segment.  */
+	    break;
+
+	  l->l_tls_blocksize = ph->p_memsz;
+	  l->l_tls_align = ph->p_align;
+	  if (ph->p_align == 0)
+	    l->l_tls_firstbyte_offset = 0;
+	  else
+	    l->l_tls_firstbyte_offset = ph->p_vaddr & (ph->p_align - 1);
+	  l->l_tls_initimage_size = ph->p_filesz;
+	  /* Since we don't know the load address yet only store the
+	     offset.  We will adjust it later.  */
+	  l->l_tls_initimage = (void *) ph->p_vaddr;
+
+	  /* If not loading the initial set of shared libraries,
+	     check whether we should permit loading a TLS segment.  */
+	  if (__glibc_likely (l->l_type == lt_library)
+	      /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
+		 not set up TLS data structures, so don't use them now.  */
+	      || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))
+	    {
+	      /* Assign the next available module ID.  */
+	      l->l_tls_modid = _dl_next_tls_modid ();
+	      break;
+	    }
+
+#ifdef SHARED
+	  /* We are loading the executable itself when the dynamic
+	     linker was executed directly.  The setup will happen
+	     later.  Otherwise, the TLS data structures are already
+	     initialized, and we assigned a TLS modid above.  */
+	  assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0);
+#else
+	  assert (false && "TLS not initialized in static application");
+#endif
+	  break;
+
+	case PT_GNU_STACK:
+	  stack_flags = ph->p_flags;
+	  break;
+
+	case PT_GNU_RELRO:
+	  l->l_relro_addr = ph->p_vaddr;
+	  l->l_relro_size = ph->p_memsz;
+	  break;
+	}
+
+    if (__glibc_unlikely (nloadcmds == 0))
+      {
+	/* This only happens for a bogus object that will be caught with
+	   another error below.  But we don't want to go through the
+	   calculations below using NLOADCMDS - 1.  */
+	errstring = N_("object file has no loadable segments");
+	goto call_lose;
+      }
+
+    if (__glibc_unlikely (type != ET_DYN)
+	&& __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))
+      {
+	/* This object is loaded at a fixed address.  This must never
+	   happen for objects loaded with dlopen.  */
+	errstring = N_("cannot dynamically load executable");
+	goto call_lose;
+      }
+
+    /* Length of the sections to be loaded.  */
+    maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
+
+    /* Now process the load commands and map segments into memory.
+       This is responsible for filling in:
+       l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr
+     */
+    errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
+				  maplength, has_holes, loader);
+    if (__glibc_unlikely (errstring != NULL))
+      goto call_lose;
+  }
+
+  if (l->l_ld == 0)
+    {
+      if (__glibc_unlikely (type == ET_DYN))
+	{
+	  errstring = N_("object file has no dynamic section");
+	  goto call_lose;
+	}
+    }
+  else
+    l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+
+  elf_get_dynamic_info (l, NULL);
+
+  /* Make sure we are not dlopen'ing an object that has the
+     DF_1_NOOPEN flag set.  */
+  if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
+      && (mode & __RTLD_DLOPEN))
+    {
+      /* We are not supposed to load this object.  Free all resources.  */
+      _dl_unmap_segments (l);
+
+      if (!l->l_libname->dont_free)
+	free (l->l_libname);
+
+      if (l->l_phdr_allocated)
+	free ((void *) l->l_phdr);
+
+      errstring = N_("shared object cannot be dlopen()ed");
+      goto call_lose;
+    }
+
+  if (l->l_phdr == NULL)
+    {
+      /* The program header is not contained in any of the segments.
+	 We have to allocate memory ourself and copy it over from out
+	 temporary place.  */
+      ElfW(Phdr) *newp = (ElfW(Phdr) *) malloc (header->e_phnum
+						* sizeof (ElfW(Phdr)));
+      if (newp == NULL)
+	{
+	  errstring = N_("cannot allocate memory for program header");
+	  goto call_lose_errno;
+	}
+
+      l->l_phdr = memcpy (newp, phdr,
+			  (header->e_phnum * sizeof (ElfW(Phdr))));
+      l->l_phdr_allocated = 1;
+    }
+  else
+    /* Adjust the PT_PHDR value by the runtime load address.  */
+    l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
+
+  if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X))
+    {
+      if (__glibc_unlikely (__check_caller (RETURN_ADDRESS (0), allow_ldso) != 0))
+	{
+	  errstring = N_("invalid caller");
+	  goto call_lose;
+	}
+
+      /* The stack is presently not executable, but this module
+	 requires that it be executable.  We must change the
+	 protection of the variable which contains the flags used in
+	 the mprotect calls.  */
+#ifdef SHARED
+      if ((mode & (__RTLD_DLOPEN | __RTLD_AUDIT)) == __RTLD_DLOPEN)
+	{
+	  const uintptr_t p = (uintptr_t) &__stack_prot & -GLRO(dl_pagesize);
+	  const size_t s = (uintptr_t) (&__stack_prot + 1) - p;
+
+	  struct link_map *const m = &GL(dl_rtld_map);
+	  const uintptr_t relro_end = ((m->l_addr + m->l_relro_addr
+					+ m->l_relro_size)
+				       & -GLRO(dl_pagesize));
+	  if (__glibc_likely (p + s <= relro_end))
+	    {
+	      /* The variable lies in the region protected by RELRO.  */
+	      if (__mprotect ((void *) p, s, PROT_READ|PROT_WRITE) < 0)
+		{
+		  errstring = N_("cannot change memory protections");
+		  goto call_lose_errno;
+		}
+	      __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+	      __mprotect ((void *) p, s, PROT_READ);
+	    }
+	  else
+	    __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+	}
+      else
+#endif
+	__stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+
+#ifdef check_consistency
+      check_consistency ();
+#endif
+
+      errval = (*GL(dl_make_stack_executable_hook)) (stack_endp);
+      if (errval)
+	{
+	  errstring = N_("\
+cannot enable executable stack as shared object requires");
+	  goto call_lose;
+	}
+    }
+
+  /* Adjust the address of the TLS initialization image.  */
+  if (l->l_tls_initimage != NULL)
+    l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
+
+  /* We are done mapping in the file.  We no longer need the descriptor.  */
+  if (__glibc_unlikely (__close (fd) != 0))
+    {
+      errstring = N_("cannot close file descriptor");
+      goto call_lose_errno;
+    }
+  /* Signal that we closed the file.  */
+  fd = -1;
+
+  /* If this is ET_EXEC, we should have loaded it as lt_executable.  */
+  assert (type != ET_EXEC || l->l_type == lt_executable);
+
+  l->l_entry += l->l_addr;
+
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+    _dl_debug_printf ("\
+  dynamic: 0x%0*lx  base: 0x%0*lx   size: 0x%0*Zx\n\
+    entry: 0x%0*lx  phdr: 0x%0*lx  phnum:   %*u\n\n",
+			   (int) sizeof (void *) * 2,
+			   (unsigned long int) l->l_ld,
+			   (int) sizeof (void *) * 2,
+			   (unsigned long int) l->l_addr,
+			   (int) sizeof (void *) * 2, maplength,
+			   (int) sizeof (void *) * 2,
+			   (unsigned long int) l->l_entry,
+			   (int) sizeof (void *) * 2,
+			   (unsigned long int) l->l_phdr,
+			   (int) sizeof (void *) * 2, l->l_phnum);
+
+  /* Set up the symbol hash table.  */
+  _dl_setup_hash (l);
+
+  /* If this object has DT_SYMBOLIC set modify now its scope.  We don't
+     have to do this for the main map.  */
+  if ((mode & RTLD_DEEPBIND) == 0
+      && __glibc_unlikely (l->l_info[DT_SYMBOLIC] != NULL)
+      && &l->l_searchlist != l->l_scope[0])
+    {
+      /* Create an appropriate searchlist.  It contains only this map.
+	 This is the definition of DT_SYMBOLIC in SysVr4.  */
+      l->l_symbolic_searchlist.r_list[0] = l;
+      l->l_symbolic_searchlist.r_nlist = 1;
+
+      /* Now move the existing entries one back.  */
+      memmove (&l->l_scope[1], &l->l_scope[0],
+	       (l->l_scope_max - 1) * sizeof (l->l_scope[0]));
+
+      /* Now add the new entry.  */
+      l->l_scope[0] = &l->l_symbolic_searchlist;
+    }
+
+  /* Remember whether this object must be initialized first.  */
+  if (l->l_flags_1 & DF_1_INITFIRST)
+    GL(dl_initfirst) = l;
+
+  /* Finally the file information.  */
+  l->l_file_id = id;
+
+#ifdef SHARED
+  /* When auditing is used the recorded names might not include the
+     name by which the DSO is actually known.  Add that as well.  */
+  if (__glibc_unlikely (origname != NULL))
+    add_name_to_object (l, origname);
+#else
+  /* Audit modules only exist when linking is dynamic so ORIGNAME
+     cannot be non-NULL.  */
+  assert (origname == NULL);
+#endif
+
+  /* When we profile the SONAME might be needed for something else but
+     loading.  Add it right away.  */
+  if (__glibc_unlikely (GLRO(dl_profile) != NULL)
+      && l->l_info[DT_SONAME] != NULL)
+    add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
+			    + l->l_info[DT_SONAME]->d_un.d_val));
+
+#ifdef DL_AFTER_LOAD
+  DL_AFTER_LOAD (l);
+#endif
+
+  /* Now that the object is fully initialized add it to the object list.  */
+  _dl_add_to_namespace_list (l, nsid);
+
+#ifdef SHARED
+  /* Auditing checkpoint: we have a new object.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0)
+      && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objopen != NULL)
+	    {
+	      l->l_audit[cnt].bindflags
+		= afct->objopen (l, nsid, &l->l_audit[cnt].cookie);
+
+	      l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0;
+	    }
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
+  return l;
+}
+
+/* Print search path.  */
+static void
+print_search_path (struct r_search_path_elem **list,
+		   const char *what, const char *name)
+{
+  char buf[max_dirnamelen + max_capstrlen];
+  int first = 1;
+
+  _dl_debug_printf (" search path=");
+
+  while (*list != NULL && (*list)->what == what) /* Yes, ==.  */
+    {
+      char *endp = __mempcpy (buf, (*list)->dirname, (*list)->dirnamelen);
+      size_t cnt;
+
+      for (cnt = 0; cnt < ncapstr; ++cnt)
+	if ((*list)->status[cnt] != nonexisting)
+	  {
+	    char *cp = __mempcpy (endp, capstr[cnt].str, capstr[cnt].len);
+	    if (cp == buf || (cp == buf + 1 && buf[0] == '/'))
+	      cp[0] = '\0';
+	    else
+	      cp[-1] = '\0';
+
+	    _dl_debug_printf_c (first ? "%s" : ":%s", buf);
+	    first = 0;
+	  }
+
+      ++list;
+    }
+
+  if (name != NULL)
+    _dl_debug_printf_c ("\t\t(%s from file %s)\n", what,
+			DSO_FILENAME (name));
+  else
+    _dl_debug_printf_c ("\t\t(%s)\n", what);
+}
+
+/* Open a file and verify it is an ELF file for this architecture.  We
+   ignore only ELF files for other architectures.  Non-ELF files and
+   ELF files with different header information cause fatal errors since
+   this could mean there is something wrong in the installation and the
+   user might want to know about this.
+
+   If FD is not -1, then the file is already open and FD refers to it.
+   In that case, FD is consumed for both successful and error returns.  */
+static int
+open_verify (const char *name, int fd,
+             struct filebuf *fbp, struct link_map *loader,
+	     int whatcode, int mode, bool *found_other_class, bool free_name)
+{
+  /* This is the expected ELF header.  */
+#define ELF32_CLASS ELFCLASS32
+#define ELF64_CLASS ELFCLASS64
+#ifndef VALID_ELF_HEADER
+# define VALID_ELF_HEADER(hdr,exp,size)	(memcmp (hdr, exp, size) == 0)
+# define VALID_ELF_OSABI(osabi)		(osabi == ELFOSABI_SYSV)
+# define VALID_ELF_ABIVERSION(osabi,ver) (ver == 0)
+#elif defined MORE_ELF_HEADER_DATA
+  MORE_ELF_HEADER_DATA;
+#endif
+  static const unsigned char expected[EI_NIDENT] =
+  {
+    [EI_MAG0] = ELFMAG0,
+    [EI_MAG1] = ELFMAG1,
+    [EI_MAG2] = ELFMAG2,
+    [EI_MAG3] = ELFMAG3,
+    [EI_CLASS] = ELFW(CLASS),
+    [EI_DATA] = byteorder,
+    [EI_VERSION] = EV_CURRENT,
+    [EI_OSABI] = ELFOSABI_SYSV,
+    [EI_ABIVERSION] = 0
+  };
+  static const struct
+  {
+    ElfW(Word) vendorlen;
+    ElfW(Word) datalen;
+    ElfW(Word) type;
+    char vendor[4];
+  } expected_note = { 4, 16, 1, "GNU" };
+  /* Initialize it to make the compiler happy.  */
+  const char *errstring = NULL;
+  int errval = 0;
+
+#ifdef SHARED
+  /* Give the auditing libraries a chance.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0
+      && loader->l_auditing == 0)
+    {
+      const char *original_name = name;
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objsearch != NULL)
+	    {
+	      name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+				      whatcode);
+	      if (name == NULL)
+		/* Ignore the path.  */
+		return -1;
+	    }
+
+	  afct = afct->next;
+	}
+
+      if (fd != -1 && name != original_name && strcmp (name, original_name))
+        {
+          /* An audit library changed what we're supposed to open,
+             so FD no longer matches it.  */
+          __close (fd);
+          fd = -1;
+        }
+    }
+#endif
+
+  if (fd == -1)
+    /* Open the file.  We always open files read-only.  */
+    fd = __open (name, O_RDONLY | O_CLOEXEC);
+
+  if (fd != -1)
+    {
+      ElfW(Ehdr) *ehdr;
+      ElfW(Phdr) *phdr, *ph;
+      ElfW(Word) *abi_note;
+      unsigned int osversion;
+      size_t maplength;
+
+      /* We successfully opened the file.  Now verify it is a file
+	 we can use.  */
+      __set_errno (0);
+      fbp->len = 0;
+      assert (sizeof (fbp->buf) > sizeof (ElfW(Ehdr)));
+      /* Read in the header.  */
+      do
+	{
+	  ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len,
+					sizeof (fbp->buf) - fbp->len);
+	  if (retlen <= 0)
+	    break;
+	  fbp->len += retlen;
+	}
+      while (__glibc_unlikely (fbp->len < sizeof (ElfW(Ehdr))));
+
+      /* This is where the ELF header is loaded.  */
+      ehdr = (ElfW(Ehdr) *) fbp->buf;
+
+      /* Now run the tests.  */
+      if (__glibc_unlikely (fbp->len < (ssize_t) sizeof (ElfW(Ehdr))))
+	{
+	  errval = errno;
+	  errstring = (errval == 0
+		       ? N_("file too short") : N_("cannot read file data"));
+	call_lose:
+	  if (free_name)
+	    {
+	      char *realname = (char *) name;
+	      name = strdupa (realname);
+	      free (realname);
+	    }
+	  lose (errval, fd, name, NULL, NULL, errstring, NULL, 0);
+	}
+
+      /* See whether the ELF header is what we expect.  */
+      if (__glibc_unlikely (! VALID_ELF_HEADER (ehdr->e_ident, expected,
+						EI_ABIVERSION)
+			    || !VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
+						      ehdr->e_ident[EI_ABIVERSION])
+			    || memcmp (&ehdr->e_ident[EI_PAD],
+				       &expected[EI_PAD],
+				       EI_NIDENT - EI_PAD) != 0))
+	{
+	  /* Something is wrong.  */
+	  const Elf32_Word *magp = (const void *) ehdr->e_ident;
+	  if (*magp !=
+#if BYTE_ORDER == LITTLE_ENDIAN
+	      ((ELFMAG0 << (EI_MAG0 * 8)) |
+	       (ELFMAG1 << (EI_MAG1 * 8)) |
+	       (ELFMAG2 << (EI_MAG2 * 8)) |
+	       (ELFMAG3 << (EI_MAG3 * 8)))
+#else
+	      ((ELFMAG0 << (EI_MAG3 * 8)) |
+	       (ELFMAG1 << (EI_MAG2 * 8)) |
+	       (ELFMAG2 << (EI_MAG1 * 8)) |
+	       (ELFMAG3 << (EI_MAG0 * 8)))
+#endif
+	      )
+	    errstring = N_("invalid ELF header");
+	  else if (ehdr->e_ident[EI_CLASS] != ELFW(CLASS))
+	    {
+	      /* This is not a fatal error.  On architectures where
+		 32-bit and 64-bit binaries can be run this might
+		 happen.  */
+	      *found_other_class = true;
+	      goto close_and_out;
+	    }
+	  else if (ehdr->e_ident[EI_DATA] != byteorder)
+	    {
+	      if (BYTE_ORDER == BIG_ENDIAN)
+		errstring = N_("ELF file data encoding not big-endian");
+	      else
+		errstring = N_("ELF file data encoding not little-endian");
+	    }
+	  else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
+	    errstring
+	      = N_("ELF file version ident does not match current one");
+	  /* XXX We should be able so set system specific versions which are
+	     allowed here.  */
+	  else if (!VALID_ELF_OSABI (ehdr->e_ident[EI_OSABI]))
+	    errstring = N_("ELF file OS ABI invalid");
+	  else if (!VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
+					  ehdr->e_ident[EI_ABIVERSION]))
+	    errstring = N_("ELF file ABI version invalid");
+	  else if (memcmp (&ehdr->e_ident[EI_PAD], &expected[EI_PAD],
+			   EI_NIDENT - EI_PAD) != 0)
+	    errstring = N_("nonzero padding in e_ident");
+	  else
+	    /* Otherwise we don't know what went wrong.  */
+	    errstring = N_("internal error");
+
+	  goto call_lose;
+	}
+
+      if (__glibc_unlikely (ehdr->e_version != EV_CURRENT))
+	{
+	  errstring = N_("ELF file version does not match current one");
+	  goto call_lose;
+	}
+      if (! __glibc_likely (elf_machine_matches_host (ehdr)))
+	goto close_and_out;
+      else if (__glibc_unlikely (ehdr->e_type != ET_DYN
+				 && ehdr->e_type != ET_EXEC))
+	{
+	  errstring = N_("only ET_DYN and ET_EXEC can be loaded");
+	  goto call_lose;
+	}
+      else if (__glibc_unlikely (ehdr->e_type == ET_EXEC
+				 && (mode & __RTLD_OPENEXEC) == 0))
+	{
+	  /* BZ #16634. It is an error to dlopen ET_EXEC (unless
+	     __RTLD_OPENEXEC is explicitly set).  We return error here
+	     so that code in _dl_map_object_from_fd does not try to set
+	     l_tls_modid for this module.  */
+
+	  errstring = N_("cannot dynamically load executable");
+	  goto call_lose;
+	}
+      else if (__glibc_unlikely (ehdr->e_phentsize != sizeof (ElfW(Phdr))))
+	{
+	  errstring = N_("ELF file's phentsize not the expected size");
+	  goto call_lose;
+	}
+
+      maplength = ehdr->e_phnum * sizeof (ElfW(Phdr));
+      if (ehdr->e_phoff + maplength <= (size_t) fbp->len)
+	phdr = (void *) (fbp->buf + ehdr->e_phoff);
+      else
+	{
+	  phdr = alloca (maplength);
+	  __lseek (fd, ehdr->e_phoff, SEEK_SET);
+	  if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
+	    {
+	    read_error:
+	      errval = errno;
+	      errstring = N_("cannot read file data");
+	      goto call_lose;
+	    }
+	}
+
+      if (__glibc_unlikely (elf_machine_reject_phdr_p
+			    (phdr, ehdr->e_phnum, fbp->buf, fbp->len,
+			     loader, fd)))
+	goto close_and_out;
+
+      /* Check .note.ABI-tag if present.  */
+      for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
+	if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
+	  {
+	    ElfW(Addr) size = ph->p_filesz;
+
+	    if (ph->p_offset + size <= (size_t) fbp->len)
+	      abi_note = (void *) (fbp->buf + ph->p_offset);
+	    else
+	      {
+		abi_note = alloca (size);
+		__lseek (fd, ph->p_offset, SEEK_SET);
+		if (__libc_read (fd, (void *) abi_note, size) != size)
+		  goto read_error;
+	      }
+
+	    while (memcmp (abi_note, &expected_note, sizeof (expected_note)))
+	      {
+#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+		ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
+				       + ROUND (abi_note[0])
+				       + ROUND (abi_note[1]);
+
+		if (size - 32 < note_size)
+		  {
+		    size = 0;
+		    break;
+		  }
+		size -= note_size;
+		abi_note = (void *) abi_note + note_size;
+	      }
+
+	    if (size == 0)
+	      continue;
+
+	    osversion = (abi_note[5] & 0xff) * 65536
+			+ (abi_note[6] & 0xff) * 256
+			+ (abi_note[7] & 0xff);
+	    if (abi_note[4] != __ABI_TAG_OS
+		|| (GLRO(dl_osversion) && GLRO(dl_osversion) < osversion))
+	      {
+	      close_and_out:
+		__close (fd);
+		__set_errno (ENOENT);
+		fd = -1;
+	      }
+
+	    break;
+	  }
+    }
+
+  return fd;
+}
+
+/* Try to open NAME in one of the directories in *DIRSP.
+   Return the fd, or -1.  If successful, fill in *REALNAME
+   with the malloc'd full directory name.  If it turns out
+   that none of the directories in *DIRSP exists, *DIRSP is
+   replaced with (void *) -1, and the old value is free()d
+   if MAY_FREE_DIRS is true.  */
+
+static int
+open_path (const char *name, size_t namelen, int mode,
+	   struct r_search_path_struct *sps, char **realname,
+	   struct filebuf *fbp, struct link_map *loader, int whatcode,
+	   bool *found_other_class)
+{
+  struct r_search_path_elem **dirs = sps->dirs;
+  char *buf;
+  int fd = -1;
+  const char *current_what = NULL;
+  int any = 0;
+
+  if (__glibc_unlikely (dirs == NULL))
+    /* We're called before _dl_init_paths when loading the main executable
+       given on the command line when rtld is run directly.  */
+    return -1;
+
+  buf = alloca (max_dirnamelen + max_capstrlen + namelen);
+  do
+    {
+      struct r_search_path_elem *this_dir = *dirs;
+      size_t buflen = 0;
+      size_t cnt;
+      char *edp;
+      int here_any = 0;
+      int err;
+
+      /* If we are debugging the search for libraries print the path
+	 now if it hasn't happened now.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)
+	  && current_what != this_dir->what)
+	{
+	  current_what = this_dir->what;
+	  print_search_path (dirs, current_what, this_dir->where);
+	}
+
+      edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen);
+      for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt)
+	{
+	  /* Skip this directory if we know it does not exist.  */
+	  if (this_dir->status[cnt] == nonexisting)
+	    continue;
+
+	  buflen =
+	    ((char *) __mempcpy (__mempcpy (edp, capstr[cnt].str,
+					    capstr[cnt].len),
+				 name, namelen)
+	     - buf);
+
+	  /* Print name we try if this is wanted.  */
+	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+	    _dl_debug_printf ("  trying file=%s\n", buf);
+
+	  fd = open_verify (buf, -1, fbp, loader, whatcode, mode,
+			    found_other_class, false);
+	  if (this_dir->status[cnt] == unknown)
+	    {
+	      if (fd != -1)
+		this_dir->status[cnt] = existing;
+	      /* Do not update the directory information when loading
+		 auditing code.  We must try to disturb the program as
+		 little as possible.  */
+	      else if (loader == NULL
+		       || GL(dl_ns)[loader->l_ns]._ns_loaded->l_auditing == 0)
+		{
+		  /* We failed to open machine dependent library.  Let's
+		     test whether there is any directory at all.  */
+		  struct stat64 st;
+
+		  buf[buflen - namelen - 1] = '\0';
+
+		  if (__xstat64 (_STAT_VER, buf, &st) != 0
+		      || ! S_ISDIR (st.st_mode))
+		    /* The directory does not exist or it is no directory.  */
+		    this_dir->status[cnt] = nonexisting;
+		  else
+		    this_dir->status[cnt] = existing;
+		}
+	    }
+
+	  /* Remember whether we found any existing directory.  */
+	  here_any |= this_dir->status[cnt] != nonexisting;
+
+	  if (fd != -1 && __glibc_unlikely (mode & __RTLD_SECURE)
+	      && __libc_enable_secure)
+	    {
+	      /* This is an extra security effort to make sure nobody can
+		 preload broken shared objects which are in the trusted
+		 directories and so exploit the bugs.  */
+	      struct stat64 st;
+
+	      if (__fxstat64 (_STAT_VER, fd, &st) != 0
+		  || (st.st_mode & S_ISUID) == 0)
+		{
+		  /* The shared object cannot be tested for being SUID
+		     or this bit is not set.  In this case we must not
+		     use this object.  */
+		  __close (fd);
+		  fd = -1;
+		  /* We simply ignore the file, signal this by setting
+		     the error value which would have been set by `open'.  */
+		  errno = ENOENT;
+		}
+	    }
+	}
+
+      if (fd != -1)
+	{
+	  *realname = (char *) malloc (buflen);
+	  if (*realname != NULL)
+	    {
+	      memcpy (*realname, buf, buflen);
+	      return fd;
+	    }
+	  else
+	    {
+	      /* No memory for the name, we certainly won't be able
+		 to load and link it.  */
+	      __close (fd);
+	      return -1;
+	    }
+	}
+      if (here_any && (err = errno) != ENOENT && err != EACCES)
+	/* The file exists and is readable, but something went wrong.  */
+	return -1;
+
+      /* Remember whether we found anything.  */
+      any |= here_any;
+    }
+  while (*++dirs != NULL);
+
+  /* Remove the whole path if none of the directories exists.  */
+  if (__glibc_unlikely (! any))
+    {
+      /* Paths which were allocated using the minimal malloc() in ld.so
+	 must not be freed using the general free() in libc.  */
+      if (sps->malloced)
+	free (sps->dirs);
+
+      /* rtld_search_dirs and env_path_list are attribute_relro, therefore
+	 avoid writing into it.  */
+      if (sps != &rtld_search_dirs && sps != &env_path_list)
+	sps->dirs = (void *) -1;
+    }
+
+  return -1;
+}
+
+/* Map in the shared object file NAME.  */
+
+struct link_map *
+internal_function
+_dl_map_object (struct link_map *loader, const char *name,
+		int type, int trace_mode, int mode, Lmid_t nsid)
+{
+  int fd;
+  const char *origname = NULL;
+  char *realname;
+  char *name_copy;
+  struct link_map *l;
+  struct filebuf fb;
+
+  assert (nsid >= 0);
+  assert (nsid < GL(dl_nns));
+
+  /* Look for this name among those already loaded.  */
+  for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
+    {
+      /* If the requested name matches the soname of a loaded object,
+	 use that object.  Elide this check for names that have not
+	 yet been opened.  */
+      if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
+	continue;
+      if (!_dl_name_match_p (name, l))
+	{
+	  const char *soname;
+
+	  if (__glibc_likely (l->l_soname_added)
+	      || l->l_info[DT_SONAME] == NULL)
+	    continue;
+
+	  soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
+		    + l->l_info[DT_SONAME]->d_un.d_val);
+	  if (strcmp (name, soname) != 0)
+	    continue;
+
+	  /* We have a match on a new name -- cache it.  */
+	  add_name_to_object (l, soname);
+	  l->l_soname_added = 1;
+	}
+
+      /* We have a match.  */
+      return l;
+    }
+
+  /* Display information if we are debugging.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
+      && loader != NULL)
+    _dl_debug_printf ((mode & __RTLD_CALLMAP) == 0
+		      ? "\nfile=%s [%lu];  needed by %s [%lu]\n"
+		      : "\nfile=%s [%lu];  dynamically loaded by %s [%lu]\n",
+		      name, nsid, DSO_FILENAME (loader->l_name), loader->l_ns);
+
+#ifdef SHARED
+  /* Give the auditing libraries a chance to change the name before we
+     try anything.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0)
+      && (loader == NULL || loader->l_auditing == 0))
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objsearch != NULL)
+	    {
+	      const char *before = name;
+	      name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+				      LA_SER_ORIG);
+	      if (name == NULL)
+		{
+		  /* Do not try anything further.  */
+		  fd = -1;
+		  goto no_file;
+		}
+	      if (before != name && strcmp (before, name) != 0)
+		{
+		  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+		    _dl_debug_printf ("audit changed filename %s -> %s\n",
+				      before, name);
+
+		  if (origname == NULL)
+		    origname = before;
+		}
+	    }
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
+  /* Will be true if we found a DSO which is of the other ELF class.  */
+  bool found_other_class = false;
+
+  if (strchr (name, '/') == NULL)
+    {
+      /* Search for NAME in several places.  */
+
+      size_t namelen = strlen (name) + 1;
+
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+	_dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid);
+
+      fd = -1;
+
+      /* When the object has the RUNPATH information we don't use any
+	 RPATHs.  */
+      if (loader == NULL || loader->l_info[DT_RUNPATH] == NULL)
+	{
+	  /* This is the executable's map (if there is one).  Make sure that
+	     we do not look at it twice.  */
+	  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+	  bool did_main_map = false;
+
+	  /* First try the DT_RPATH of the dependent object that caused NAME
+	     to be loaded.  Then that object's dependent, and on up.  */
+	  for (l = loader; l; l = l->l_loader)
+	    if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
+	      {
+		fd = open_path (name, namelen, mode,
+				&l->l_rpath_dirs,
+				&realname, &fb, loader, LA_SER_RUNPATH,
+				&found_other_class);
+		if (fd != -1)
+		  break;
+
+		did_main_map |= l == main_map;
+	      }
+
+	  /* If dynamically linked, try the DT_RPATH of the executable
+	     itself.  NB: we do this for lookups in any namespace.  */
+	  if (fd == -1 && !did_main_map
+	      && main_map != NULL && main_map->l_type != lt_loaded
+	      && cache_rpath (main_map, &main_map->l_rpath_dirs, DT_RPATH,
+			      "RPATH"))
+	    fd = open_path (name, namelen, mode,
+			    &main_map->l_rpath_dirs,
+			    &realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
+			    &found_other_class);
+	}
+
+      /* Try the LD_LIBRARY_PATH environment variable.  */
+      if (fd == -1 && env_path_list.dirs != (void *) -1)
+	fd = open_path (name, namelen, mode, &env_path_list,
+			&realname, &fb,
+			loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
+			LA_SER_LIBPATH, &found_other_class);
+
+      /* Look at the RUNPATH information for this binary.  */
+      if (fd == -1 && loader != NULL
+	  && cache_rpath (loader, &loader->l_runpath_dirs,
+			  DT_RUNPATH, "RUNPATH"))
+	fd = open_path (name, namelen, mode,
+			&loader->l_runpath_dirs, &realname, &fb, loader,
+			LA_SER_RUNPATH, &found_other_class);
+
+      if (fd == -1)
+        {
+          realname = _dl_sysdep_open_object (name, namelen, &fd);
+          if (realname != NULL)
+            {
+              fd = open_verify (realname, fd,
+                                &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
+                                LA_SER_CONFIG, mode, &found_other_class,
+                                false);
+              if (fd == -1)
+                free (realname);
+            }
+        }
+
+#ifdef USE_LDCONFIG
+      if (fd == -1
+	  && (__glibc_likely ((mode & __RTLD_SECURE) == 0)
+	      || ! __libc_enable_secure)
+	  && __glibc_likely (GLRO(dl_inhibit_cache) == 0))
+	{
+	  /* Check the list of libraries in the file /etc/ld.so.cache,
+	     for compatibility with Linux's ldconfig program.  */
+	  char *cached = _dl_load_cache_lookup (name);
+
+	  if (cached != NULL)
+	    {
+	      // XXX Correct to unconditionally default to namespace 0?
+	      l = (loader
+		   ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded
+# ifdef SHARED
+		   ?: &GL(dl_rtld_map)
+# endif
+		  );
+
+	      /* If the loader has the DF_1_NODEFLIB flag set we must not
+		 use a cache entry from any of these directories.  */
+	      if (__glibc_unlikely (l->l_flags_1 & DF_1_NODEFLIB))
+		{
+		  const char *dirp = system_dirs;
+		  unsigned int cnt = 0;
+
+		  do
+		    {
+		      if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0)
+			{
+			  /* The prefix matches.  Don't use the entry.  */
+			  free (cached);
+			  cached = NULL;
+			  break;
+			}
+
+		      dirp += system_dirs_len[cnt] + 1;
+		      ++cnt;
+		    }
+		  while (cnt < nsystem_dirs_len);
+		}
+
+	      if (cached != NULL)
+		{
+		  fd = open_verify (cached, -1,
+				    &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
+				    LA_SER_CONFIG, mode, &found_other_class,
+				    false);
+		  if (__glibc_likely (fd != -1))
+		    realname = cached;
+		  else
+		    free (cached);
+		}
+	    }
+	}
+#endif
+
+      /* Finally, try the default path.  */
+      if (fd == -1
+	  && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
+	      || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB)))
+	  && rtld_search_dirs.dirs != (void *) -1)
+	fd = open_path (name, namelen, mode, &rtld_search_dirs,
+			&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
+
+      /* Add another newline when we are tracing the library loading.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+	_dl_debug_printf ("\n");
+    }
+  else
+    {
+      /* The path may contain dynamic string tokens.  */
+      realname = (loader
+		  ? expand_dynamic_string_token (loader, name, 0)
+		  : __strdup (name));
+      if (realname == NULL)
+	fd = -1;
+      else
+	{
+	  fd = open_verify (realname, -1, &fb,
+			    loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode,
+			    &found_other_class, true);
+	  if (__glibc_unlikely (fd == -1))
+	    free (realname);
+	}
+    }
+
+#ifdef SHARED
+ no_file:
+#endif
+  /* In case the LOADER information has only been provided to get to
+     the appropriate RUNPATH/RPATH information we do not need it
+     anymore.  */
+  if (mode & __RTLD_CALLMAP)
+    loader = NULL;
+
+  if (__glibc_unlikely (fd == -1))
+    {
+      if (trace_mode
+	  && __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0))
+	{
+	  /* We haven't found an appropriate library.  But since we
+	     are only interested in the list of libraries this isn't
+	     so severe.  Fake an entry with all the information we
+	     have.  */
+	  static const Elf_Symndx dummy_bucket = STN_UNDEF;
+
+	  /* Allocate a new object map.  */
+	  if ((name_copy = __strdup (name)) == NULL
+	      || (l = _dl_new_object (name_copy, name, type, loader,
+				      mode, nsid)) == NULL)
+	    {
+	      free (name_copy);
+	      _dl_signal_error (ENOMEM, name, NULL,
+				N_("cannot create shared object descriptor"));
+	    }
+	  /* Signal that this is a faked entry.  */
+	  l->l_faked = 1;
+	  /* Since the descriptor is initialized with zero we do not
+	     have do this here.
+	  l->l_reserved = 0; */
+	  l->l_buckets = &dummy_bucket;
+	  l->l_nbuckets = 1;
+	  l->l_relocated = 1;
+
+	  /* Enter the object in the object list.  */
+	  _dl_add_to_namespace_list (l, nsid);
+
+	  return l;
+	}
+      else if (found_other_class)
+	_dl_signal_error (0, name, NULL,
+			  ELFW(CLASS) == ELFCLASS32
+			  ? N_("wrong ELF class: ELFCLASS64")
+			  : N_("wrong ELF class: ELFCLASS32"));
+      else
+	_dl_signal_error (errno, name, NULL,
+			  N_("cannot open shared object file"));
+    }
+
+  void *stack_end = __libc_stack_end;
+  return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader,
+				 type, mode, &stack_end, nsid);
+}
+
+struct add_path_state
+{
+  bool counting;
+  unsigned int idx;
+  Dl_serinfo *si;
+  char *allocptr;
+};
+
+static void
+add_path (struct add_path_state *p, const struct r_search_path_struct *sps,
+	  unsigned int flags)
+{
+  if (sps->dirs != (void *) -1)
+    {
+      struct r_search_path_elem **dirs = sps->dirs;
+      do
+	{
+	  const struct r_search_path_elem *const r = *dirs++;
+	  if (p->counting)
+	    {
+	      p->si->dls_cnt++;
+	      p->si->dls_size += MAX (2, r->dirnamelen);
+	    }
+	  else
+	    {
+	      Dl_serpath *const sp = &p->si->dls_serpath[p->idx++];
+	      sp->dls_name = p->allocptr;
+	      if (r->dirnamelen < 2)
+		*p->allocptr++ = r->dirnamelen ? '/' : '.';
+	      else
+		p->allocptr = __mempcpy (p->allocptr,
+					  r->dirname, r->dirnamelen - 1);
+	      *p->allocptr++ = '\0';
+	      sp->dls_flags = flags;
+	    }
+	}
+      while (*dirs != NULL);
+    }
+}
+
+void
+internal_function
+_dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
+{
+  if (counting)
+    {
+      si->dls_cnt = 0;
+      si->dls_size = 0;
+    }
+
+  struct add_path_state p =
+    {
+      .counting = counting,
+      .idx = 0,
+      .si = si,
+      .allocptr = (char *) &si->dls_serpath[si->dls_cnt]
+    };
+
+# define add_path(p, sps, flags) add_path(p, sps, 0) /* XXX */
+
+  /* When the object has the RUNPATH information we don't use any RPATHs.  */
+  if (loader->l_info[DT_RUNPATH] == NULL)
+    {
+      /* First try the DT_RPATH of the dependent object that caused NAME
+	 to be loaded.  Then that object's dependent, and on up.  */
+
+      struct link_map *l = loader;
+      do
+	{
+	  if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
+	    add_path (&p, &l->l_rpath_dirs, XXX_RPATH);
+	  l = l->l_loader;
+	}
+      while (l != NULL);
+
+      /* If dynamically linked, try the DT_RPATH of the executable itself.  */
+      if (loader->l_ns == LM_ID_BASE)
+	{
+	  l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+	  if (l != NULL && l->l_type != lt_loaded && l != loader)
+	    if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
+	      add_path (&p, &l->l_rpath_dirs, XXX_RPATH);
+	}
+    }
+
+  /* Try the LD_LIBRARY_PATH environment variable.  */
+  add_path (&p, &env_path_list, XXX_ENV);
+
+  /* Look at the RUNPATH information for this binary.  */
+  if (cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH"))
+    add_path (&p, &loader->l_runpath_dirs, XXX_RUNPATH);
+
+  /* XXX
+     Here is where ld.so.cache gets checked, but we don't have
+     a way to indicate that in the results for Dl_serinfo.  */
+
+  /* Finally, try the default path.  */
+  if (!(loader->l_flags_1 & DF_1_NODEFLIB))
+    add_path (&p, &rtld_search_dirs, XXX_default);
+
+  if (counting)
+    /* Count the struct size before the string area, which we didn't
+       know before we completed dls_cnt.  */
+    si->dls_size += (char *) &si->dls_serpath[si->dls_cnt] - (char *) si;
+}
diff --git a/REORG.TODO/elf/dl-load.h b/REORG.TODO/elf/dl-load.h
new file mode 100644
index 0000000000..7cd6214d4e
--- /dev/null
+++ b/REORG.TODO/elf/dl-load.h
@@ -0,0 +1,135 @@
+/* Map in a shared object's segments from the file.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_LOAD_H
+#define _DL_LOAD_H	1
+
+#include <link.h>
+#include <sys/mman.h>
+
+
+/* On some systems, no flag bits are given to specify file mapping.  */
+#ifndef MAP_FILE
+# define MAP_FILE       0
+#endif
+
+/* The right way to map in the shared library files is MAP_COPY, which
+   makes a virtual copy of the data at the time of the mmap call; this
+   guarantees the mapped pages will be consistent even if the file is
+   overwritten.  Some losing VM systems like Linux's lack MAP_COPY.  All we
+   get is MAP_PRIVATE, which copies each page when it is modified; this
+   means if the file is overwritten, we may at some point get some pages
+   from the new version after starting with pages from the old version.
+
+   To make up for the lack and avoid the overwriting problem,
+   what Linux does have is MAP_DENYWRITE.  This prevents anyone
+   from modifying the file while we have it mapped.  */
+#ifndef MAP_COPY
+# ifdef MAP_DENYWRITE
+#  define MAP_COPY      (MAP_PRIVATE | MAP_DENYWRITE)
+# else
+#  define MAP_COPY      MAP_PRIVATE
+# endif
+#endif
+
+/* Some systems link their relocatable objects for another base address
+   than 0.  We want to know the base address for these such that we can
+   subtract this address from the segment addresses during mapping.
+   This results in a more efficient address space usage.  Defaults to
+   zero for almost all systems.  */
+#ifndef MAP_BASE_ADDR
+# define MAP_BASE_ADDR(l)       0
+#endif
+
+
+/* Handle situations where we have a preferred location in memory for
+   the shared objects.  */
+#ifdef ELF_PREFERRED_ADDRESS_DATA
+ELF_PREFERRED_ADDRESS_DATA;
+#endif
+#ifndef ELF_PREFERRED_ADDRESS
+# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
+#endif
+#ifndef ELF_FIXED_ADDRESS
+# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
+#endif
+
+
+/* This structure describes one PT_LOAD command.
+   Its details have been expanded out and converted.  */
+struct loadcmd
+{
+  ElfW(Addr) mapstart, mapend, dataend, allocend;
+  ElfW(Off) mapoff;
+  int prot;                             /* PROT_* bits.  */
+};
+
+
+/* This is a subroutine of _dl_map_segments.  It should be called for each
+   load command, some time after L->l_addr has been set correctly.  It is
+   responsible for setting up the l_text_end and l_phdr fields.  */
+static void __always_inline
+_dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,
+                         const struct loadcmd *c)
+{
+  if (c->prot & PROT_EXEC)
+    l->l_text_end = l->l_addr + c->mapend;
+
+  if (l->l_phdr == 0
+      && c->mapoff <= header->e_phoff
+      && ((size_t) (c->mapend - c->mapstart + c->mapoff)
+          >= header->e_phoff + header->e_phnum * sizeof (ElfW(Phdr))))
+    /* Found the program header in this segment.  */
+    l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff
+                                      - c->mapoff);
+}
+
+
+/* This is a subroutine of _dl_map_object_from_fd.  It is responsible
+   for filling in several fields in *L: l_map_start, l_map_end, l_addr,
+   l_contiguous, l_text_end, l_phdr.  On successful return, all the
+   segments are mapped (or copied, or whatever) from the file into their
+   final places in the address space, with the correct page permissions,
+   and any bss-like regions already zeroed.  It returns a null pointer
+   on success, or an error message string (to be translated) on error
+   (having also set errno).
+
+   The file <dl-map-segments.h> defines this function.  The canonical
+   implementation in elf/dl-map-segments.h might be replaced by a sysdeps
+   version.  */
+static const char *_dl_map_segments (struct link_map *l, int fd,
+                                     const ElfW(Ehdr) *header, int type,
+                                     const struct loadcmd loadcmds[],
+                                     size_t nloadcmds,
+                                     const size_t maplength,
+                                     bool has_holes,
+                                     struct link_map *loader);
+
+/* All the error message strings _dl_map_segments might return are
+   listed here so that different implementations in different sysdeps
+   dl-map-segments.h files all use consistent strings that are
+   guaranteed to have translations.  */
+#define DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT \
+  N_("failed to map segment from shared object")
+#define DL_MAP_SEGMENTS_ERROR_MPROTECT \
+  N_("cannot change memory protections")
+#define DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL \
+  N_("cannot map zero-fill pages")
+
+
+#endif	/* dl-load.h */
diff --git a/REORG.TODO/elf/dl-lookup.c b/REORG.TODO/elf/dl-lookup.c
new file mode 100644
index 0000000000..3d2369dbf2
--- /dev/null
+++ b/REORG.TODO/elf/dl-lookup.c
@@ -0,0 +1,1129 @@
+/* Look up a symbol in the loaded objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <alloca.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-hash.h>
+#include <dl-machine.h>
+#include <sysdep-cancel.h>
+#include <libc-lock.h>
+#include <tls.h>
+#include <atomic.h>
+
+#include <assert.h>
+
+/* Return nonzero if check_match should consider SYM to fail to match a
+   symbol reference for some machine-specific reason.  */
+#ifndef ELF_MACHINE_SYM_NO_MATCH
+# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
+#endif
+
+#define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
+
+
+struct sym_val
+  {
+    const ElfW(Sym) *s;
+    struct link_map *m;
+  };
+
+
+#define make_string(string, rest...) \
+  ({									      \
+    const char *all[] = { string, ## rest };				      \
+    size_t len, cnt;							      \
+    char *result, *cp;							      \
+									      \
+    len = 1;								      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      len += strlen (all[cnt]);						      \
+									      \
+    cp = result = alloca (len);						      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      cp = __stpcpy (cp, all[cnt]);					      \
+									      \
+    result;								      \
+  })
+
+/* Statistics function.  */
+#ifdef SHARED
+# define bump_num_relocations() ++GL(dl_num_relocations)
+#else
+# define bump_num_relocations() ((void) 0)
+#endif
+
+/* Utility function for do_lookup_x. The caller is called with undef_name,
+   ref, version, flags and type_class, and those are passed as the first
+   five arguments. The caller then computes sym, symidx, strtab, and map
+   and passes them as the next four arguments. Lastly the caller passes in
+   versioned_sym and num_versions which are modified by check_match during
+   the checking process.  */
+static const ElfW(Sym) *
+check_match (const char *const undef_name,
+	     const ElfW(Sym) *const ref,
+	     const struct r_found_version *const version,
+	     const int flags,
+	     const int type_class,
+	     const ElfW(Sym) *const sym,
+	     const Elf_Symndx symidx,
+	     const char *const strtab,
+	     const struct link_map *const map,
+	     const ElfW(Sym) **const versioned_sym,
+	     int *const num_versions)
+{
+  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
+  assert (ELF_RTYPE_CLASS_PLT == 1);
+  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
+			 && stt != STT_TLS)
+			|| ELF_MACHINE_SYM_NO_MATCH (sym)
+			|| (type_class & (sym->st_shndx == SHN_UNDEF))))
+    return NULL;
+
+  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
+     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
+     code/data definitions.  */
+#define ALLOWED_STT \
+  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
+   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
+  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
+    return NULL;
+
+  if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
+    /* Not the symbol we are looking for.  */
+    return NULL;
+
+  const ElfW(Half) *verstab = map->l_versyms;
+  if (version != NULL)
+    {
+      if (__glibc_unlikely (verstab == NULL))
+	{
+	  /* We need a versioned symbol but haven't found any.  If
+	     this is the object which is referenced in the verneed
+	     entry it is a bug in the library since a symbol must
+	     not simply disappear.
+
+	     It would also be a bug in the object since it means that
+	     the list of required versions is incomplete and so the
+	     tests in dl-version.c haven't found a problem.*/
+	  assert (version->filename == NULL
+		  || ! _dl_name_match_p (version->filename, map));
+
+	  /* Otherwise we accept the symbol.  */
+	}
+      else
+	{
+	  /* We can match the version information or use the
+	     default one if it is not hidden.  */
+	  ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+	  if ((map->l_versions[ndx].hash != version->hash
+	       || strcmp (map->l_versions[ndx].name, version->name))
+	      && (version->hidden || map->l_versions[ndx].hash
+		  || (verstab[symidx] & 0x8000)))
+	    /* It's not the version we want.  */
+	    return NULL;
+	}
+    }
+  else
+    {
+      /* No specific version is selected.  There are two ways we
+	 can got here:
+
+	 - a binary which does not include versioning information
+	 is loaded
+
+	 - dlsym() instead of dlvsym() is used to get a symbol which
+	 might exist in more than one form
+
+	 If the library does not provide symbol version information
+	 there is no problem at all: we simply use the symbol if it
+	 is defined.
+
+	 These two lookups need to be handled differently if the
+	 library defines versions.  In the case of the old
+	 unversioned application the oldest (default) version
+	 should be used.  In case of a dlsym() call the latest and
+	 public interface should be returned.  */
+      if (verstab != NULL)
+	{
+	  if ((verstab[symidx] & 0x7fff)
+	      >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
+	    {
+	      /* Don't accept hidden symbols.  */
+	      if ((verstab[symidx] & 0x8000) == 0
+		  && (*num_versions)++ == 0)
+		/* No version so far.  */
+		*versioned_sym = sym;
+
+	      return NULL;
+	    }
+	}
+    }
+
+  /* There cannot be another entry for this symbol so stop here.  */
+  return sym;
+}
+
+/* Utility function for do_lookup_unique.  Add a symbol to TABLE.  */
+static void
+enter_unique_sym (struct unique_sym *table, size_t size,
+                  unsigned int hash, const char *name,
+                  const ElfW(Sym) *sym, const struct link_map *map)
+{
+  size_t idx = hash % size;
+  size_t hash2 = 1 + hash % (size - 2);
+  while (table[idx].name != NULL)
+    {
+      idx += hash2;
+      if (idx >= size)
+        idx -= size;
+    }
+
+  table[idx].hashval = hash;
+  table[idx].name = name;
+  table[idx].sym = sym;
+  table[idx].map = map;
+}
+
+/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
+   in the unique symbol table, creating a new entry if necessary.
+   Return the matching symbol in RESULT.  */
+static void
+do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
+		  const struct link_map *map, struct sym_val *result,
+		  int type_class, const ElfW(Sym) *sym, const char *strtab,
+		  const ElfW(Sym) *ref, const struct link_map *undef_map)
+{
+  /* We have to determine whether we already found a symbol with this
+     name before.  If not then we have to add it to the search table.
+     If we already found a definition we have to use it.  */
+
+  struct unique_sym_table *tab
+    = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
+
+  __rtld_lock_lock_recursive (tab->lock);
+
+  struct unique_sym *entries = tab->entries;
+  size_t size = tab->size;
+  if (entries != NULL)
+    {
+      size_t idx = new_hash % size;
+      size_t hash2 = 1 + new_hash % (size - 2);
+      while (1)
+	{
+	  if (entries[idx].hashval == new_hash
+	      && strcmp (entries[idx].name, undef_name) == 0)
+	    {
+	      if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+		{
+		  /* We possibly have to initialize the central
+		     copy from the copy addressed through the
+		     relocation.  */
+		  result->s = sym;
+		  result->m = (struct link_map *) map;
+		}
+	      else
+		{
+		  result->s = entries[idx].sym;
+		  result->m = (struct link_map *) entries[idx].map;
+		}
+	      __rtld_lock_unlock_recursive (tab->lock);
+	      return;
+	    }
+
+	  if (entries[idx].name == NULL)
+	    break;
+
+	  idx += hash2;
+	  if (idx >= size)
+	    idx -= size;
+	}
+
+      if (size * 3 <= tab->n_elements * 4)
+	{
+	  /* Expand the table.  */
+#ifdef RTLD_CHECK_FOREIGN_CALL
+	  /* This must not happen during runtime relocations.  */
+	  assert (!RTLD_CHECK_FOREIGN_CALL);
+#endif
+	  size_t newsize = _dl_higher_prime_number (size + 1);
+	  struct unique_sym *newentries
+	    = calloc (sizeof (struct unique_sym), newsize);
+	  if (newentries == NULL)
+	    {
+	    nomem:
+	      __rtld_lock_unlock_recursive (tab->lock);
+	      _dl_fatal_printf ("out of memory\n");
+	    }
+
+	  for (idx = 0; idx < size; ++idx)
+	    if (entries[idx].name != NULL)
+	      enter_unique_sym (newentries, newsize, entries[idx].hashval,
+                                entries[idx].name, entries[idx].sym,
+                                entries[idx].map);
+
+	  tab->free (entries);
+	  tab->size = newsize;
+	  size = newsize;
+	  entries = tab->entries = newentries;
+	  tab->free = free;
+	}
+    }
+  else
+    {
+#ifdef RTLD_CHECK_FOREIGN_CALL
+      /* This must not happen during runtime relocations.  */
+      assert (!RTLD_CHECK_FOREIGN_CALL);
+#endif
+
+#ifdef SHARED
+      /* If tab->entries is NULL, but tab->size is not, it means
+	 this is the second, conflict finding, lookup for
+	 LD_TRACE_PRELINKING in _dl_debug_bindings.  Don't
+	 allocate anything and don't enter anything into the
+	 hash table.  */
+      if (__glibc_unlikely (tab->size))
+	{
+	  assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
+	  goto success;
+	}
+#endif
+
+#define INITIAL_NUNIQUE_SYM_TABLE 31
+      size = INITIAL_NUNIQUE_SYM_TABLE;
+      entries = calloc (sizeof (struct unique_sym), size);
+      if (entries == NULL)
+	goto nomem;
+
+      tab->entries = entries;
+      tab->size = size;
+      tab->free = free;
+    }
+
+  if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+    enter_unique_sym (entries, size, new_hash, strtab + sym->st_name, ref,
+	   undef_map);
+  else
+    {
+      enter_unique_sym (entries, size,
+                        new_hash, strtab + sym->st_name, sym, map);
+
+      if (map->l_type == lt_loaded)
+	/* Make sure we don't unload this object by
+	   setting the appropriate flag.  */
+	((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
+    }
+  ++tab->n_elements;
+
+#ifdef SHARED
+ success:
+#endif
+  __rtld_lock_unlock_recursive (tab->lock);
+
+  result->s = sym;
+  result->m = (struct link_map *) map;
+}
+
+/* Inner part of the lookup functions.  We return a value > 0 if we
+   found the symbol, the value 0 if nothing is found and < 0 if
+   something bad happened.  */
+static int
+__attribute_noinline__
+do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
+	     unsigned long int *old_hash, const ElfW(Sym) *ref,
+	     struct sym_val *result, struct r_scope_elem *scope, size_t i,
+	     const struct r_found_version *const version, int flags,
+	     struct link_map *skip, int type_class, struct link_map *undef_map)
+{
+  size_t n = scope->r_nlist;
+  /* Make sure we read the value before proceeding.  Otherwise we
+     might use r_list pointing to the initial scope and r_nlist being
+     the value after a resize.  That is the only path in dl-open.c not
+     protected by GSCOPE.  A read barrier here might be to expensive.  */
+  __asm volatile ("" : "+r" (n), "+m" (scope->r_list));
+  struct link_map **list = scope->r_list;
+
+  do
+    {
+      const struct link_map *map = list[i]->l_real;
+
+      /* Here come the extra test needed for `_dl_lookup_symbol_skip'.  */
+      if (map == skip)
+	continue;
+
+      /* Don't search the executable when resolving a copy reloc.  */
+      if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
+	continue;
+
+      /* Do not look into objects which are going to be removed.  */
+      if (map->l_removed)
+	continue;
+
+      /* Print some debugging info if wanted.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
+	_dl_debug_printf ("symbol=%s;  lookup in file=%s [%lu]\n",
+			  undef_name, DSO_FILENAME (map->l_name),
+			  map->l_ns);
+
+      /* If the hash table is empty there is nothing to do here.  */
+      if (map->l_nbuckets == 0)
+	continue;
+
+      Elf_Symndx symidx;
+      int num_versions = 0;
+      const ElfW(Sym) *versioned_sym = NULL;
+
+      /* The tables for this map.  */
+      const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+      const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+      const ElfW(Sym) *sym;
+      const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
+      if (__glibc_likely (bitmask != NULL))
+	{
+	  ElfW(Addr) bitmask_word
+	    = bitmask[(new_hash / __ELF_NATIVE_CLASS)
+		      & map->l_gnu_bitmask_idxbits];
+
+	  unsigned int hashbit1 = new_hash & (__ELF_NATIVE_CLASS - 1);
+	  unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift)
+				   & (__ELF_NATIVE_CLASS - 1));
+
+	  if (__glibc_unlikely ((bitmask_word >> hashbit1)
+				& (bitmask_word >> hashbit2) & 1))
+	    {
+	      Elf32_Word bucket = map->l_gnu_buckets[new_hash
+						     % map->l_nbuckets];
+	      if (bucket != 0)
+		{
+		  const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
+
+		  do
+		    if (((*hasharr ^ new_hash) >> 1) == 0)
+		      {
+			symidx = hasharr - map->l_gnu_chain_zero;
+			sym = check_match (undef_name, ref, version, flags,
+					   type_class, &symtab[symidx], symidx,
+					   strtab, map, &versioned_sym,
+					   &num_versions);
+			if (sym != NULL)
+			  goto found_it;
+		      }
+		  while ((*hasharr++ & 1u) == 0);
+		}
+	    }
+	  /* No symbol found.  */
+	  symidx = SHN_UNDEF;
+	}
+      else
+	{
+	  if (*old_hash == 0xffffffff)
+	    *old_hash = _dl_elf_hash (undef_name);
+
+	  /* Use the old SysV-style hash table.  Search the appropriate
+	     hash bucket in this object's symbol table for a definition
+	     for the same symbol name.  */
+	  for (symidx = map->l_buckets[*old_hash % map->l_nbuckets];
+	       symidx != STN_UNDEF;
+	       symidx = map->l_chain[symidx])
+	    {
+	      sym = check_match (undef_name, ref, version, flags,
+				 type_class, &symtab[symidx], symidx,
+				 strtab, map, &versioned_sym,
+				 &num_versions);
+	      if (sym != NULL)
+		goto found_it;
+	    }
+	}
+
+      /* If we have seen exactly one versioned symbol while we are
+	 looking for an unversioned symbol and the version is not the
+	 default version we still accept this symbol since there are
+	 no possible ambiguities.  */
+      sym = num_versions == 1 ? versioned_sym : NULL;
+
+      if (sym != NULL)
+	{
+	found_it:
+	  /* When UNDEF_MAP is NULL, which indicates we are called from
+	     do_lookup_x on relocation against protected data, we skip
+	     the data definion in the executable from copy reloc.  */
+	  if (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+	      && undef_map == NULL
+	      && map->l_type == lt_executable
+	      && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+	    {
+	      const ElfW(Sym) *s;
+	      unsigned int i;
+
+#if ! ELF_MACHINE_NO_RELA
+	      if (map->l_info[DT_RELA] != NULL
+		  && map->l_info[DT_RELASZ] != NULL
+		  && map->l_info[DT_RELASZ]->d_un.d_val != 0)
+		{
+		  const ElfW(Rela) *rela
+		    = (const ElfW(Rela) *) D_PTR (map, l_info[DT_RELA]);
+		  unsigned int rela_count
+		    = map->l_info[DT_RELASZ]->d_un.d_val / sizeof (*rela);
+
+		  for (i = 0; i < rela_count; i++, rela++)
+		    if (elf_machine_type_class (ELFW(R_TYPE) (rela->r_info))
+			== ELF_RTYPE_CLASS_COPY)
+		      {
+			s = &symtab[ELFW(R_SYM) (rela->r_info)];
+			if (!strcmp (strtab + s->st_name, undef_name))
+			  goto skip;
+		      }
+		}
+#endif
+#if ! ELF_MACHINE_NO_REL
+	      if (map->l_info[DT_REL] != NULL
+		  && map->l_info[DT_RELSZ] != NULL
+		  && map->l_info[DT_RELSZ]->d_un.d_val != 0)
+		{
+		  const ElfW(Rel) *rel
+		    = (const ElfW(Rel) *) D_PTR (map, l_info[DT_REL]);
+		  unsigned int rel_count
+		    = map->l_info[DT_RELSZ]->d_un.d_val / sizeof (*rel);
+
+		  for (i = 0; i < rel_count; i++, rel++)
+		    if (elf_machine_type_class (ELFW(R_TYPE) (rel->r_info))
+			== ELF_RTYPE_CLASS_COPY)
+		      {
+			s = &symtab[ELFW(R_SYM) (rel->r_info)];
+			if (!strcmp (strtab + s->st_name, undef_name))
+			  goto skip;
+		      }
+		}
+#endif
+	    }
+
+	  /* Hidden and internal symbols are local, ignore them.  */
+	  if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym)))
+	    goto skip;
+
+	  switch (ELFW(ST_BIND) (sym->st_info))
+	    {
+	    case STB_WEAK:
+	      /* Weak definition.  Use this value if we don't find another.  */
+	      if (__glibc_unlikely (GLRO(dl_dynamic_weak)))
+		{
+		  if (! result->s)
+		    {
+		      result->s = sym;
+		      result->m = (struct link_map *) map;
+		    }
+		  break;
+		}
+	      /* FALLTHROUGH */
+	    case STB_GLOBAL:
+	      /* Global definition.  Just what we need.  */
+	      result->s = sym;
+	      result->m = (struct link_map *) map;
+	      return 1;
+
+	    case STB_GNU_UNIQUE:;
+	      do_lookup_unique (undef_name, new_hash, map, result, type_class,
+				sym, strtab, ref, undef_map);
+	      return 1;
+
+	    default:
+	      /* Local symbols are ignored.  */
+	      break;
+	    }
+	}
+
+skip:
+      /* If this current map is the one mentioned in the verneed entry
+	 and we have not found a weak entry, it is a bug.  */
+      if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
+	  && __glibc_unlikely (_dl_name_match_p (version->filename, map)))
+	return -1;
+    }
+  while (++i < n);
+
+  /* We have not found anything until now.  */
+  return 0;
+}
+
+
+static uint_fast32_t
+dl_new_hash (const char *s)
+{
+  uint_fast32_t h = 5381;
+  for (unsigned char c = *s; c != '\0'; c = *++s)
+    h = h * 33 + c;
+  return h & 0xffffffff;
+}
+
+
+/* Add extra dependency on MAP to UNDEF_MAP.  */
+static int
+internal_function
+add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
+{
+  struct link_map *runp;
+  unsigned int i;
+  int result = 0;
+
+  /* Avoid self-references and references to objects which cannot be
+     unloaded anyway.  */
+  if (undef_map == map)
+    return 0;
+
+  /* Avoid references to objects which cannot be unloaded anyway.  */
+  assert (map->l_type == lt_loaded);
+  if ((map->l_flags_1 & DF_1_NODELETE) != 0)
+    return 0;
+
+  struct link_map_reldeps *l_reldeps
+    = atomic_forced_read (undef_map->l_reldeps);
+
+  /* Make sure l_reldeps is read before l_initfini.  */
+  atomic_read_barrier ();
+
+  /* Determine whether UNDEF_MAP already has a reference to MAP.  First
+     look in the normal dependencies.  */
+  struct link_map **l_initfini = atomic_forced_read (undef_map->l_initfini);
+  if (l_initfini != NULL)
+    {
+      for (i = 0; l_initfini[i] != NULL; ++i)
+	if (l_initfini[i] == map)
+	  return 0;
+    }
+
+  /* No normal dependency.  See whether we already had to add it
+     to the special list of dynamic dependencies.  */
+  unsigned int l_reldepsact = 0;
+  if (l_reldeps != NULL)
+    {
+      struct link_map **list = &l_reldeps->list[0];
+      l_reldepsact = l_reldeps->act;
+      for (i = 0; i < l_reldepsact; ++i)
+	if (list[i] == map)
+	  return 0;
+    }
+
+  /* Save serial number of the target MAP.  */
+  unsigned long long serial = map->l_serial;
+
+  /* Make sure nobody can unload the object while we are at it.  */
+  if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
+    {
+      /* We can't just call __rtld_lock_lock_recursive (GL(dl_load_lock))
+	 here, that can result in ABBA deadlock.  */
+      THREAD_GSCOPE_RESET_FLAG ();
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+      /* While MAP value won't change, after THREAD_GSCOPE_RESET_FLAG ()
+	 it can e.g. point to unallocated memory.  So avoid the optimizer
+	 treating the above read from MAP->l_serial as ensurance it
+	 can safely dereference it.  */
+      map = atomic_forced_read (map);
+
+      /* From this point on it is unsafe to dereference MAP, until it
+	 has been found in one of the lists.  */
+
+      /* Redo the l_initfini check in case undef_map's l_initfini
+	 changed in the mean time.  */
+      if (undef_map->l_initfini != l_initfini
+	  && undef_map->l_initfini != NULL)
+	{
+	  l_initfini = undef_map->l_initfini;
+	  for (i = 0; l_initfini[i] != NULL; ++i)
+	    if (l_initfini[i] == map)
+	      goto out_check;
+	}
+
+      /* Redo the l_reldeps check if undef_map's l_reldeps changed in
+	 the mean time.  */
+      if (undef_map->l_reldeps != NULL)
+	{
+	  if (undef_map->l_reldeps != l_reldeps)
+	    {
+	      struct link_map **list = &undef_map->l_reldeps->list[0];
+	      l_reldepsact = undef_map->l_reldeps->act;
+	      for (i = 0; i < l_reldepsact; ++i)
+		if (list[i] == map)
+		  goto out_check;
+	    }
+	  else if (undef_map->l_reldeps->act > l_reldepsact)
+	    {
+	      struct link_map **list
+		= &undef_map->l_reldeps->list[0];
+	      i = l_reldepsact;
+	      l_reldepsact = undef_map->l_reldeps->act;
+	      for (; i < l_reldepsact; ++i)
+		if (list[i] == map)
+		  goto out_check;
+	    }
+	}
+    }
+  else
+    __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  /* The object is not yet in the dependency list.  Before we add
+     it make sure just one more time the object we are about to
+     reference is still available.  There is a brief period in
+     which the object could have been removed since we found the
+     definition.  */
+  runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded;
+  while (runp != NULL && runp != map)
+    runp = runp->l_next;
+
+  if (runp != NULL)
+    {
+      /* The object is still available.  */
+
+      /* MAP could have been dlclosed, freed and then some other dlopened
+	 library could have the same link_map pointer.  */
+      if (map->l_serial != serial)
+	goto out_check;
+
+      /* Redo the NODELETE check, as when dl_load_lock wasn't held
+	 yet this could have changed.  */
+      if ((map->l_flags_1 & DF_1_NODELETE) != 0)
+	goto out;
+
+      /* If the object with the undefined reference cannot be removed ever
+	 just make sure the same is true for the object which contains the
+	 definition.  */
+      if (undef_map->l_type != lt_loaded
+	  || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
+	{
+	  map->l_flags_1 |= DF_1_NODELETE;
+	  goto out;
+	}
+
+      /* Add the reference now.  */
+      if (__glibc_unlikely (l_reldepsact >= undef_map->l_reldepsmax))
+	{
+	  /* Allocate more memory for the dependency list.  Since this
+	     can never happen during the startup phase we can use
+	     `realloc'.  */
+	  struct link_map_reldeps *newp;
+	  unsigned int max
+	    = undef_map->l_reldepsmax ? undef_map->l_reldepsmax * 2 : 10;
+
+#ifdef RTLD_PREPARE_FOREIGN_CALL
+	  RTLD_PREPARE_FOREIGN_CALL;
+#endif
+
+	  newp = malloc (sizeof (*newp) + max * sizeof (struct link_map *));
+	  if (newp == NULL)
+	    {
+	      /* If we didn't manage to allocate memory for the list this is
+		 no fatal problem.  We simply make sure the referenced object
+		 cannot be unloaded.  This is semantically the correct
+		 behavior.  */
+	      map->l_flags_1 |= DF_1_NODELETE;
+	      goto out;
+	    }
+	  else
+	    {
+	      if (l_reldepsact)
+		memcpy (&newp->list[0], &undef_map->l_reldeps->list[0],
+			l_reldepsact * sizeof (struct link_map *));
+	      newp->list[l_reldepsact] = map;
+	      newp->act = l_reldepsact + 1;
+	      atomic_write_barrier ();
+	      void *old = undef_map->l_reldeps;
+	      undef_map->l_reldeps = newp;
+	      undef_map->l_reldepsmax = max;
+	      if (old)
+		_dl_scope_free (old);
+	    }
+	}
+      else
+	{
+	  undef_map->l_reldeps->list[l_reldepsact] = map;
+	  atomic_write_barrier ();
+	  undef_map->l_reldeps->act = l_reldepsact + 1;
+	}
+
+      /* Display information if we are debugging.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+	_dl_debug_printf ("\
+\nfile=%s [%lu];  needed by %s [%lu] (relocation dependency)\n\n",
+			  DSO_FILENAME (map->l_name),
+			  map->l_ns,
+			  DSO_FILENAME (undef_map->l_name),
+			  undef_map->l_ns);
+    }
+  else
+    /* Whoa, that was bad luck.  We have to search again.  */
+    result = -1;
+
+ out:
+  /* Release the lock.  */
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+  if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
+    THREAD_GSCOPE_SET_FLAG ();
+
+  return result;
+
+ out_check:
+  if (map->l_serial != serial)
+    result = -1;
+  goto out;
+}
+
+static void
+internal_function
+_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
+		    const ElfW(Sym) **ref, struct sym_val *value,
+		    const struct r_found_version *version, int type_class,
+		    int protected);
+
+
+/* Search loaded objects' symbol tables for a definition of the symbol
+   UNDEF_NAME, perhaps with a requested version for the symbol.
+
+   We must never have calls to the audit functions inside this function
+   or in any function which gets called.  If this would happen the audit
+   code might create a thread which can throw off all the scope locking.  */
+lookup_t
+internal_function
+_dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
+		     const ElfW(Sym) **ref,
+		     struct r_scope_elem *symbol_scope[],
+		     const struct r_found_version *version,
+		     int type_class, int flags, struct link_map *skip_map)
+{
+  const uint_fast32_t new_hash = dl_new_hash (undef_name);
+  unsigned long int old_hash = 0xffffffff;
+  struct sym_val current_value = { NULL, NULL };
+  struct r_scope_elem **scope = symbol_scope;
+
+  bump_num_relocations ();
+
+  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK
+     is allowed if we look up a versioned symbol.  */
+  assert (version == NULL
+	  || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK))
+	     == 0);
+
+  size_t i = 0;
+  if (__glibc_unlikely (skip_map != NULL))
+    /* Search the relevant loaded objects for a definition.  */
+    while ((*scope)->r_list[i] != skip_map)
+      ++i;
+
+  /* Search the relevant loaded objects for a definition.  */
+  for (size_t start = i; *scope != NULL; start = 0, ++scope)
+    {
+      int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+			     &current_value, *scope, start, version, flags,
+			     skip_map, type_class, undef_map);
+      if (res > 0)
+	break;
+
+      if (__glibc_unlikely (res < 0) && skip_map == NULL)
+	{
+	  /* Oh, oh.  The file named in the relocation entry does not
+	     contain the needed symbol.  This code is never reached
+	     for unversioned lookups.  */
+	  assert (version != NULL);
+	  const char *reference_name = undef_map ? undef_map->l_name : "";
+
+	  /* XXX We cannot translate the message.  */
+	  _dl_signal_cerror (0, DSO_FILENAME (reference_name),
+			     N_("relocation error"),
+			     make_string ("symbol ", undef_name, ", version ",
+					  version->name,
+					  " not defined in file ",
+					  version->filename,
+					  " with link time reference",
+					  res == -2
+					  ? " (no version symbols)" : ""));
+	  *ref = NULL;
+	  return 0;
+	}
+    }
+
+  if (__glibc_unlikely (current_value.s == NULL))
+    {
+      if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
+	  && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
+	{
+	  /* We could find no value for a strong reference.  */
+	  const char *reference_name = undef_map ? undef_map->l_name : "";
+	  const char *versionstr = version ? ", version " : "";
+	  const char *versionname = (version && version->name
+				     ? version->name : "");
+
+	  /* XXX We cannot translate the message.  */
+	  _dl_signal_cerror (0, DSO_FILENAME (reference_name),
+			     N_("symbol lookup error"),
+			     make_string ("undefined symbol: ", undef_name,
+					  versionstr, versionname));
+	}
+      *ref = NULL;
+      return 0;
+    }
+
+  int protected = (*ref
+		   && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
+  if (__glibc_unlikely (protected != 0))
+    {
+      /* It is very tricky.  We need to figure out what value to
+	 return for the protected symbol.  */
+      if (type_class == ELF_RTYPE_CLASS_PLT)
+	{
+	  if (current_value.s != NULL && current_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
+	}
+      else
+	{
+	  struct sym_val protected_value = { NULL, NULL };
+
+	  for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
+	    if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+			     &protected_value, *scope, i, version, flags,
+			     skip_map,
+			     (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+			      && ELFW(ST_TYPE) ((*ref)->st_info) == STT_OBJECT
+			      && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+			     ? ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+			     : ELF_RTYPE_CLASS_PLT, NULL) != 0)
+	      break;
+
+	  if (protected_value.s != NULL && protected_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
+	}
+    }
+
+  /* We have to check whether this would bind UNDEF_MAP to an object
+     in the global scope which was dynamically loaded.  In this case
+     we have to prevent the latter from being unloaded unless the
+     UNDEF_MAP object is also unloaded.  */
+  if (__glibc_unlikely (current_value.m->l_type == lt_loaded)
+      /* Don't do this for explicit lookups as opposed to implicit
+	 runtime lookups.  */
+      && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
+      /* Add UNDEF_MAP to the dependencies.  */
+      && add_dependency (undef_map, current_value.m, flags) < 0)
+      /* Something went wrong.  Perhaps the object we tried to reference
+	 was just removed.  Try finding another definition.  */
+      return _dl_lookup_symbol_x (undef_name, undef_map, ref,
+				  (flags & DL_LOOKUP_GSCOPE_LOCK)
+				  ? undef_map->l_scope : symbol_scope,
+				  version, type_class, flags, skip_map);
+
+  /* The object is used.  */
+  if (__glibc_unlikely (current_value.m->l_used == 0))
+    current_value.m->l_used = 1;
+
+  if (__glibc_unlikely (GLRO(dl_debug_mask)
+			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK)))
+    _dl_debug_bindings (undef_name, undef_map, ref,
+			&current_value, version, type_class, protected);
+
+  *ref = current_value.s;
+  return LOOKUP_VALUE (current_value.m);
+}
+
+
+/* Cache the location of MAP's hash table.  */
+
+void
+internal_function
+_dl_setup_hash (struct link_map *map)
+{
+  Elf_Symndx *hash;
+
+  if (__glibc_likely (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+				    + DT_THISPROCNUM + DT_VERSIONTAGNUM
+				    + DT_EXTRANUM + DT_VALNUM] != NULL))
+    {
+      Elf32_Word *hash32
+	= (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+				      + DT_THISPROCNUM + DT_VERSIONTAGNUM
+				      + DT_EXTRANUM + DT_VALNUM]);
+      map->l_nbuckets = *hash32++;
+      Elf32_Word symbias = *hash32++;
+      Elf32_Word bitmask_nwords = *hash32++;
+      /* Must be a power of two.  */
+      assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
+      map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
+      map->l_gnu_shift = *hash32++;
+
+      map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
+      hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
+
+      map->l_gnu_buckets = hash32;
+      hash32 += map->l_nbuckets;
+      map->l_gnu_chain_zero = hash32 - symbias;
+      return;
+    }
+
+  if (!map->l_info[DT_HASH])
+    return;
+  hash = (void *) D_PTR (map, l_info[DT_HASH]);
+
+  map->l_nbuckets = *hash++;
+  /* Skip nchain.  */
+  hash++;
+  map->l_buckets = hash;
+  hash += map->l_nbuckets;
+  map->l_chain = hash;
+}
+
+
+static void
+internal_function
+_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
+		    const ElfW(Sym) **ref, struct sym_val *value,
+		    const struct r_found_version *version, int type_class,
+		    int protected)
+{
+  const char *reference_name = undef_map->l_name;
+
+  if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
+    {
+      _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
+			DSO_FILENAME (reference_name),
+			undef_map->l_ns,
+			DSO_FILENAME (value->m->l_name),
+			value->m->l_ns,
+			protected ? "protected" : "normal", undef_name);
+      if (version)
+	_dl_debug_printf_c (" [%s]\n", version->name);
+      else
+	_dl_debug_printf_c ("\n");
+    }
+#ifdef SHARED
+  if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
+    {
+/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with
+   LD_TRACE_PRELINKING.  */
+#define RTYPE_CLASS_VALID	8
+#define RTYPE_CLASS_PLT		(8|1)
+#define RTYPE_CLASS_COPY	(8|2)
+#define RTYPE_CLASS_TLS		(8|4)
+#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1
+# error ELF_RTYPE_CLASS_PLT must be 0 or 1!
+#endif
+#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2
+# error ELF_RTYPE_CLASS_COPY must be 0 or 2!
+#endif
+      int conflict = 0;
+      struct sym_val val = { NULL, NULL };
+
+      if ((GLRO(dl_trace_prelink_map) == NULL
+	   || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
+	  && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
+	{
+	  const uint_fast32_t new_hash = dl_new_hash (undef_name);
+	  unsigned long int old_hash = 0xffffffff;
+	  struct unique_sym *saved_entries
+	    = GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries;
+
+	  GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL;
+	  do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
+		       undef_map->l_local_scope[0], 0, version, 0, NULL,
+		       type_class, undef_map);
+	  if (val.s != value->s || val.m != value->m)
+	    conflict = 1;
+	  else if (__glibc_unlikely (undef_map->l_symbolic_in_local_scope)
+		   && val.s
+		   && __glibc_unlikely (ELFW(ST_BIND) (val.s->st_info)
+					== STB_GNU_UNIQUE))
+	    {
+	      /* If it is STB_GNU_UNIQUE and undef_map's l_local_scope
+		 contains any DT_SYMBOLIC libraries, unfortunately there
+		 can be conflicts even if the above is equal.  As symbol
+		 resolution goes from the last library to the first and
+		 if a STB_GNU_UNIQUE symbol is found in some late DT_SYMBOLIC
+		 library, it would be the one that is looked up.  */
+	      struct sym_val val2 = { NULL, NULL };
+	      size_t n;
+	      struct r_scope_elem *scope = undef_map->l_local_scope[0];
+
+	      for (n = 0; n < scope->r_nlist; n++)
+		if (scope->r_list[n] == val.m)
+		  break;
+
+	      for (n++; n < scope->r_nlist; n++)
+		if (scope->r_list[n]->l_info[DT_SYMBOLIC] != NULL
+		    && do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+				    &val2,
+				    &scope->r_list[n]->l_symbolic_searchlist,
+				    0, version, 0, NULL, type_class,
+				    undef_map) > 0)
+		  {
+		    conflict = 1;
+		    val = val2;
+		    break;
+		  }
+	    }
+	  GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries;
+	}
+
+      if (value->s)
+	{
+	  /* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY
+	     bits since since prelink only uses them.  */
+	  type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY;
+	  if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
+				== STT_TLS))
+	    /* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS.  */
+	    type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID;
+	  else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
+				     == STT_GNU_IFUNC))
+	    /* Set the RTYPE_CLASS_VALID bit.  */
+	    type_class |= RTYPE_CLASS_VALID;
+	}
+
+      if (conflict
+	  || GLRO(dl_trace_prelink_map) == undef_map
+	  || GLRO(dl_trace_prelink_map) == NULL
+	  || type_class >= 4)
+	{
+	  _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
+		      conflict ? "conflict" : "lookup",
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (size_t) undef_map->l_map_start,
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (size_t) (value->s ? value->m->l_map_start : 0),
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (size_t) (value->s ? value->s->st_value : 0));
+
+	  if (conflict)
+	    _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
+			(int) sizeof (ElfW(Addr)) * 2,
+			(size_t) (val.s ? val.m->l_map_start : 0),
+			(int) sizeof (ElfW(Addr)) * 2,
+			(size_t) (val.s ? val.s->st_value : 0));
+
+	  _dl_printf ("/%x %s\n", type_class, undef_name);
+	}
+    }
+#endif
+}
diff --git a/REORG.TODO/elf/dl-machine-reject-phdr.h b/REORG.TODO/elf/dl-machine-reject-phdr.h
new file mode 100644
index 0000000000..57253deb52
--- /dev/null
+++ b/REORG.TODO/elf/dl-machine-reject-phdr.h
@@ -0,0 +1,34 @@
+/* Machine-dependent program header inspection for the ELF loader.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_MACHINE_REJECT_PHDR_H
+#define _DL_MACHINE_REJECT_PHDR_H 1
+
+#include <stdbool.h>
+
+/* Return true iff ELF program headers are incompatible with the running
+   host.  */
+static inline bool
+elf_machine_reject_phdr_p (const ElfW(Phdr) *phdr, uint_fast16_t phnum,
+			   const char *buf, size_t len, struct link_map *map,
+			   int fd)
+{
+  return false;
+}
+
+#endif /* dl-machine-reject-phdr.h */
diff --git a/REORG.TODO/elf/dl-map-segments.h b/REORG.TODO/elf/dl-map-segments.h
new file mode 100644
index 0000000000..d36f9bd2f6
--- /dev/null
+++ b/REORG.TODO/elf/dl-map-segments.h
@@ -0,0 +1,157 @@
+/* Map in a shared object's segments.  Generic version.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dl-load.h>
+
+/* This implementation assumes (as does the corresponding implementation
+   of _dl_unmap_segments, in dl-unmap-segments.h) that shared objects
+   are always laid out with all segments contiguous (or with gaps
+   between them small enough that it's preferable to reserve all whole
+   pages inside the gaps with PROT_NONE mappings rather than permitting
+   other use of those parts of the address space).  */
+
+static __always_inline const char *
+_dl_map_segments (struct link_map *l, int fd,
+                  const ElfW(Ehdr) *header, int type,
+                  const struct loadcmd loadcmds[], size_t nloadcmds,
+                  const size_t maplength, bool has_holes,
+                  struct link_map *loader)
+{
+  const struct loadcmd *c = loadcmds;
+
+  if (__glibc_likely (type == ET_DYN))
+    {
+      /* This is a position-independent shared object.  We can let the
+         kernel map it anywhere it likes, but we must have space for all
+         the segments in their specified positions relative to the first.
+         So we map the first segment without MAP_FIXED, but with its
+         extent increased to cover all the segments.  Then we remove
+         access from excess portion, and there is known sufficient space
+         there to remap from the later segments.
+
+         As a refinement, sometimes we have an address that we would
+         prefer to map such objects at; but this is only a preference,
+         the OS can do whatever it likes. */
+      ElfW(Addr) mappref
+        = (ELF_PREFERRED_ADDRESS (loader, maplength,
+                                  c->mapstart & GLRO(dl_use_load_bias))
+           - MAP_BASE_ADDR (l));
+
+      /* Remember which part of the address space this object uses.  */
+      l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
+                                            c->prot,
+                                            MAP_COPY|MAP_FILE,
+                                            fd, c->mapoff);
+      if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
+        return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+      l->l_map_end = l->l_map_start + maplength;
+      l->l_addr = l->l_map_start - c->mapstart;
+
+      if (has_holes)
+        {
+          /* Change protection on the excess portion to disallow all access;
+             the portions we do not remap later will be inaccessible as if
+             unallocated.  Then jump into the normal segment-mapping loop to
+             handle the portion of the segment past the end of the file
+             mapping.  */
+          if (__glibc_unlikely
+              (__mprotect ((caddr_t) (l->l_addr + c->mapend),
+                           loadcmds[nloadcmds - 1].mapstart - c->mapend,
+                           PROT_NONE) < 0))
+            return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+        }
+
+      l->l_contiguous = 1;
+
+      goto postmap;
+    }
+
+  /* Remember which part of the address space this object uses.  */
+  l->l_map_start = c->mapstart + l->l_addr;
+  l->l_map_end = l->l_map_start + maplength;
+  l->l_contiguous = !has_holes;
+
+  while (c < &loadcmds[nloadcmds])
+    {
+      if (c->mapend > c->mapstart
+          /* Map the segment contents from the file.  */
+          && (__mmap ((void *) (l->l_addr + c->mapstart),
+                      c->mapend - c->mapstart, c->prot,
+                      MAP_FIXED|MAP_COPY|MAP_FILE,
+                      fd, c->mapoff)
+              == MAP_FAILED))
+        return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+    postmap:
+      _dl_postprocess_loadcmd (l, header, c);
+
+      if (c->allocend > c->dataend)
+        {
+          /* Extra zero pages should appear at the end of this segment,
+             after the data mapped from the file.   */
+          ElfW(Addr) zero, zeroend, zeropage;
+
+          zero = l->l_addr + c->dataend;
+          zeroend = l->l_addr + c->allocend;
+          zeropage = ((zero + GLRO(dl_pagesize) - 1)
+                      & ~(GLRO(dl_pagesize) - 1));
+
+          if (zeroend < zeropage)
+            /* All the extra data is in the last page of the segment.
+               We can just zero it.  */
+            zeropage = zeroend;
+
+          if (zeropage > zero)
+            {
+              /* Zero the final part of the last page of the segment.  */
+              if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
+                {
+                  /* Dag nab it.  */
+                  if (__mprotect ((caddr_t) (zero
+                                             & ~(GLRO(dl_pagesize) - 1)),
+                                  GLRO(dl_pagesize), c->prot|PROT_WRITE) < 0)
+                    return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+                }
+              memset ((void *) zero, '\0', zeropage - zero);
+              if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
+                __mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
+                            GLRO(dl_pagesize), c->prot);
+            }
+
+          if (zeroend > zeropage)
+            {
+              /* Map the remaining zero pages in from the zero fill FD.  */
+              caddr_t mapat;
+              mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
+                              c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+                              -1, 0);
+              if (__glibc_unlikely (mapat == MAP_FAILED))
+                return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
+            }
+        }
+
+      ++c;
+    }
+
+  /* Notify ELF_PREFERRED_ADDRESS that we have to load this one
+     fixed.  */
+  ELF_FIXED_ADDRESS (loader, c->mapstart);
+
+  return NULL;
+}
diff --git a/REORG.TODO/elf/dl-minimal.c b/REORG.TODO/elf/dl-minimal.c
new file mode 100644
index 0000000000..1a35baff2e
--- /dev/null
+++ b/REORG.TODO/elf/dl-minimal.c
@@ -0,0 +1,380 @@
+/* Minimal replacements for basic facilities used in the dynamic linker.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <tls.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <ldsodefs.h>
+#include <_itoa.h>
+#include <malloc/malloc-internal.h>
+
+#include <assert.h>
+
+/* Minimal malloc allocator for used during initial link.  After the
+   initial link, a full malloc implementation is interposed, either
+   the one in libc, or a different one supplied by the user through
+   interposition.  */
+
+static void *alloc_ptr, *alloc_end, *alloc_last_block;
+
+/* Declarations of global functions.  */
+extern void weak_function free (void *ptr);
+extern void * weak_function realloc (void *ptr, size_t n);
+extern unsigned long int weak_function __strtoul_internal (const char *nptr,
+							   char **endptr,
+							   int base,
+							   int group);
+extern unsigned long int weak_function strtoul (const char *nptr,
+						char **endptr, int base);
+
+
+/* Allocate an aligned memory block.  */
+void * weak_function
+malloc (size_t n)
+{
+  if (alloc_end == 0)
+    {
+      /* Consume any unused space in the last page of our data segment.  */
+      extern int _end attribute_hidden;
+      alloc_ptr = &_end;
+      alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0)
+				 + GLRO(dl_pagesize) - 1)
+				& ~(GLRO(dl_pagesize) - 1));
+    }
+
+  /* Make sure the allocation pointer is ideally aligned.  */
+  alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + MALLOC_ALIGNMENT - 1)
+			    & ~(MALLOC_ALIGNMENT - 1));
+
+  if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr)
+    {
+      /* Insufficient space left; allocate another page plus one extra
+	 page to reduce number of mmap calls.  */
+      caddr_t page;
+      size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
+      if (__glibc_unlikely (nup == 0 && n != 0))
+	return NULL;
+      nup += GLRO(dl_pagesize);
+      page = __mmap (0, nup, PROT_READ|PROT_WRITE,
+		     MAP_ANON|MAP_PRIVATE, -1, 0);
+      if (page == MAP_FAILED)
+	return NULL;
+      if (page != alloc_end)
+	alloc_ptr = page;
+      alloc_end = page + nup;
+    }
+
+  alloc_last_block = (void *) alloc_ptr;
+  alloc_ptr += n;
+  return alloc_last_block;
+}
+
+/* We use this function occasionally since the real implementation may
+   be optimized when it can assume the memory it returns already is
+   set to NUL.  */
+void * weak_function
+calloc (size_t nmemb, size_t size)
+{
+  /* New memory from the trivial malloc above is always already cleared.
+     (We make sure that's true in the rare occasion it might not be,
+     by clearing memory in free, below.)  */
+  size_t bytes = nmemb * size;
+
+#define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2))
+  if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0)
+      && size != 0 && bytes / size != nmemb)
+    return NULL;
+
+  return malloc (bytes);
+}
+
+/* This will rarely be called.  */
+void weak_function
+free (void *ptr)
+{
+  /* We can free only the last block allocated.  */
+  if (ptr == alloc_last_block)
+    {
+      /* Since this is rare, we clear the freed block here
+	 so that calloc can presume malloc returns cleared memory.  */
+      memset (alloc_last_block, '\0', alloc_ptr - alloc_last_block);
+      alloc_ptr = alloc_last_block;
+    }
+}
+
+/* This is only called with the most recent block returned by malloc.  */
+void * weak_function
+realloc (void *ptr, size_t n)
+{
+  if (ptr == NULL)
+    return malloc (n);
+  assert (ptr == alloc_last_block);
+  size_t old_size = alloc_ptr - alloc_last_block;
+  alloc_ptr = alloc_last_block;
+  void *new = malloc (n);
+  return new != ptr ? memcpy (new, ptr, old_size) : new;
+}
+
+/* Avoid signal frobnication in setjmp/longjmp.  Keeps things smaller.  */
+
+#include <setjmp.h>
+
+int weak_function
+__sigjmp_save (sigjmp_buf env, int savemask __attribute__ ((unused)))
+{
+  env[0].__mask_was_saved = 0;
+  return 0;
+}
+
+/* Define our own version of the internal function used by strerror.  We
+   only provide the messages for some common errors.  This avoids pulling
+   in the whole error list.  */
+
+char * weak_function
+__strerror_r (int errnum, char *buf, size_t buflen)
+{
+  char *msg;
+
+  switch (errnum)
+    {
+    case ENOMEM:
+      msg = (char *) "Cannot allocate memory";
+      break;
+    case EINVAL:
+      msg = (char *) "Invalid argument";
+      break;
+    case ENOENT:
+      msg = (char *) "No such file or directory";
+      break;
+    case EPERM:
+      msg = (char *) "Operation not permitted";
+      break;
+    case EIO:
+      msg = (char *) "Input/output error";
+      break;
+    case EACCES:
+      msg = (char *) "Permission denied";
+      break;
+    default:
+      /* No need to check buffer size, all calls in the dynamic linker
+	 provide enough space.  */
+      buf[buflen - 1] = '\0';
+      msg = _itoa (errnum, buf + buflen - 1, 10, 0);
+      msg = memcpy (msg - (sizeof ("Error ") - 1), "Error ",
+		    sizeof ("Error ") - 1);
+      break;
+    }
+
+  return msg;
+}
+
+void
+__libc_fatal (const char *message)
+{
+  _dl_fatal_printf ("%s", message);
+}
+rtld_hidden_def (__libc_fatal)
+
+void
+__attribute__ ((noreturn))
+__chk_fail (void)
+{
+  _exit (127);
+}
+rtld_hidden_def (__chk_fail)
+
+#ifndef NDEBUG
+/* Define (weakly) our own assert failure function which doesn't use stdio.
+   If we are linked into the user program (-ldl), the normal __assert_fail
+   defn can override this one.  */
+
+void weak_function
+__assert_fail (const char *assertion,
+	       const char *file, unsigned int line, const char *function)
+{
+  _dl_fatal_printf ("\
+Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
+		    file, line, function ?: "", function ? ": " : "",
+		    assertion);
+
+}
+rtld_hidden_weak (__assert_fail)
+
+void weak_function
+__assert_perror_fail (int errnum,
+		      const char *file, unsigned int line,
+		      const char *function)
+{
+  char errbuf[400];
+  _dl_fatal_printf ("\
+Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n",
+		    file, line, function ?: "", function ? ": " : "",
+		    __strerror_r (errnum, errbuf, sizeof errbuf));
+
+}
+rtld_hidden_weak (__assert_perror_fail)
+#endif
+
+unsigned long int weak_function
+__strtoul_internal (const char *nptr, char **endptr, int base, int group)
+{
+  unsigned long int result = 0;
+  long int sign = 1;
+  unsigned max_digit;
+
+  while (*nptr == ' ' || *nptr == '\t')
+    ++nptr;
+
+  if (*nptr == '-')
+    {
+      sign = -1;
+      ++nptr;
+    }
+  else if (*nptr == '+')
+    ++nptr;
+
+  if (*nptr < '0' || *nptr > '9')
+    {
+      if (endptr != NULL)
+	*endptr = (char *) nptr;
+      return 0UL;
+    }
+
+  assert (base == 0);
+  base = 10;
+  max_digit = 9;
+  if (*nptr == '0')
+    {
+      if (nptr[1] == 'x' || nptr[1] == 'X')
+	{
+	  base = 16;
+	  nptr += 2;
+	}
+      else
+	{
+	  base = 8;
+	  max_digit = 7;
+	}
+    }
+
+  while (1)
+    {
+      unsigned long int digval;
+      if (*nptr >= '0' && *nptr <= '0' + max_digit)
+        digval = *nptr - '0';
+      else if (base == 16)
+        {
+	  if (*nptr >= 'a' && *nptr <= 'f')
+	    digval = *nptr - 'a' + 10;
+	  else if (*nptr >= 'A' && *nptr <= 'F')
+	    digval = *nptr - 'A' + 10;
+	  else
+	    break;
+	}
+      else
+        break;
+
+      if (result > ULONG_MAX / base
+	  || (result == ULONG_MAX / base && digval > ULONG_MAX % base))
+	{
+	  errno = ERANGE;
+	  if (endptr != NULL)
+	    *endptr = (char *) nptr;
+	  return ULONG_MAX;
+	}
+      result *= base;
+      result += digval;
+      ++nptr;
+    }
+
+  if (endptr != NULL)
+    *endptr = (char *) nptr;
+  return result * sign;
+}
+
+
+#undef _itoa
+/* We always use _itoa instead of _itoa_word in ld.so since the former
+   also has to be present and it is never about speed when these
+   functions are used.  */
+char *
+_itoa (unsigned long long int value, char *buflim, unsigned int base,
+       int upper_case)
+{
+  assert (! upper_case);
+
+  do
+    *--buflim = _itoa_lower_digits[value % base];
+  while ((value /= base) != 0);
+
+  return buflim;
+}
+
+/* The '_itoa_lower_digits' variable in libc.so is able to handle bases
+   up to 36.  We don't need this here.  */
+const char _itoa_lower_digits[16] = "0123456789abcdef";
+rtld_hidden_data_def (_itoa_lower_digits)
+
+/* The following is not a complete strsep implementation.  It cannot
+   handle empty delimiter strings.  But this isn't necessary for the
+   execution of ld.so.  */
+#undef strsep
+#undef __strsep
+char *
+__strsep (char **stringp, const char *delim)
+{
+  char *begin;
+
+  assert (delim[0] != '\0');
+
+  begin = *stringp;
+  if (begin != NULL)
+    {
+      char *end = begin;
+
+      while (*end != '\0' || (end = NULL))
+	{
+	  const char *dp = delim;
+
+	  do
+	    if (*dp == *end)
+	      break;
+	  while (*++dp != '\0');
+
+	  if (*dp != '\0')
+	    {
+	      *end++ = '\0';
+	      break;
+	    }
+
+	  ++end;
+	}
+
+      *stringp = end;
+    }
+
+  return begin;
+}
+weak_alias (__strsep, strsep)
+strong_alias (__strsep, __strsep_g)
diff --git a/REORG.TODO/elf/dl-misc.c b/REORG.TODO/elf/dl-misc.c
new file mode 100644
index 0000000000..c5d3e0e7c5
--- /dev/null
+++ b/REORG.TODO/elf/dl-misc.c
@@ -0,0 +1,362 @@
+/* Miscellaneous support functions for dynamic linker
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <ldsodefs.h>
+#include <limits.h>
+#include <link.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sysdep.h>
+#include <_itoa.h>
+#include <dl-writev.h>
+
+
+/* Read the whole contents of FILE into new mmap'd space with given
+   protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
+   is returned.  */
+
+void *
+internal_function
+_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
+{
+  void *result = MAP_FAILED;
+  struct stat64 st;
+  int fd = __open (file, O_RDONLY | O_CLOEXEC);
+  if (fd >= 0)
+    {
+      if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
+	{
+	  *sizep = st.st_size;
+
+	  /* No need to map the file if it is empty.  */
+	  if (*sizep != 0)
+	    /* Map a copy of the file contents.  */
+	    result = __mmap (NULL, *sizep, prot,
+#ifdef MAP_COPY
+			     MAP_COPY
+#else
+			     MAP_PRIVATE
+#endif
+#ifdef MAP_FILE
+			     | MAP_FILE
+#endif
+			     , fd, 0);
+	}
+      __close (fd);
+    }
+  return result;
+}
+
+
+/* Bare-bones printf implementation.  This function only knows about
+   the formats and flags needed and can handle only up to 64 stripes in
+   the output.  */
+static void
+_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+{
+# define NIOVMAX 64
+  struct iovec iov[NIOVMAX];
+  int niov = 0;
+  pid_t pid = 0;
+  char pidbuf[12];
+
+  while (*fmt != '\0')
+    {
+      const char *startp = fmt;
+
+      if (tag_p > 0)
+	{
+	  /* Generate the tag line once.  It consists of the PID and a
+	     colon followed by a tab.  */
+	  if (pid == 0)
+	    {
+	      char *p;
+	      pid = __getpid ();
+	      assert (pid >= 0 && sizeof (pid_t) <= 4);
+	      p = _itoa (pid, &pidbuf[10], 10, 0);
+	      while (p > pidbuf)
+		*--p = ' ';
+	      pidbuf[10] = ':';
+	      pidbuf[11] = '\t';
+	    }
+
+	  /* Append to the output.  */
+	  assert (niov < NIOVMAX);
+	  iov[niov].iov_len = 12;
+	  iov[niov++].iov_base = pidbuf;
+
+	  /* No more tags until we see the next newline.  */
+	  tag_p = -1;
+	}
+
+      /* Skip everything except % and \n (if tags are needed).  */
+      while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
+	++fmt;
+
+      /* Append constant string.  */
+      assert (niov < NIOVMAX);
+      if ((iov[niov].iov_len = fmt - startp) != 0)
+	iov[niov++].iov_base = (char *) startp;
+
+      if (*fmt == '%')
+	{
+	  /* It is a format specifier.  */
+	  char fill = ' ';
+	  int width = -1;
+	  int prec = -1;
+#if LONG_MAX != INT_MAX
+	  int long_mod = 0;
+#endif
+
+	  /* Recognize zero-digit fill flag.  */
+	  if (*++fmt == '0')
+	    {
+	      fill = '0';
+	      ++fmt;
+	    }
+
+	  /* See whether with comes from a parameter.  Note that no other
+	     way to specify the width is implemented.  */
+	  if (*fmt == '*')
+	    {
+	      width = va_arg (arg, int);
+	      ++fmt;
+	    }
+
+	  /* Handle precision.  */
+	  if (*fmt == '.' && fmt[1] == '*')
+	    {
+	      prec = va_arg (arg, int);
+	      fmt += 2;
+	    }
+
+	  /* Recognize the l modifier.  It is only important on some
+	     platforms where long and int have a different size.  We
+	     can use the same code for size_t.  */
+	  if (*fmt == 'l' || *fmt == 'Z')
+	    {
+#if LONG_MAX != INT_MAX
+	      long_mod = 1;
+#endif
+	      ++fmt;
+	    }
+
+	  switch (*fmt)
+	    {
+	      /* Integer formatting.  */
+	    case 'u':
+	    case 'x':
+	      {
+		/* We have to make a difference if long and int have a
+		   different size.  */
+#if LONG_MAX != INT_MAX
+		unsigned long int num = (long_mod
+					 ? va_arg (arg, unsigned long int)
+					 : va_arg (arg, unsigned int));
+#else
+		unsigned long int num = va_arg (arg, unsigned int);
+#endif
+		/* We use alloca() to allocate the buffer with the most
+		   pessimistic guess for the size.  Using alloca() allows
+		   having more than one integer formatting in a call.  */
+		char *buf = (char *) alloca (3 * sizeof (unsigned long int));
+		char *endp = &buf[3 * sizeof (unsigned long int)];
+		char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
+
+		/* Pad to the width the user specified.  */
+		if (width != -1)
+		  while (endp - cp < width)
+		    *--cp = fill;
+
+		iov[niov].iov_base = cp;
+		iov[niov].iov_len = endp - cp;
+		++niov;
+	      }
+	      break;
+
+	    case 's':
+	      /* Get the string argument.  */
+	      iov[niov].iov_base = va_arg (arg, char *);
+	      iov[niov].iov_len = strlen (iov[niov].iov_base);
+	      if (prec != -1)
+		iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
+	      ++niov;
+	      break;
+
+	    case '%':
+	      iov[niov].iov_base = (void *) fmt;
+	      iov[niov].iov_len = 1;
+	      ++niov;
+	      break;
+
+	    default:
+	      assert (! "invalid format specifier");
+	    }
+	  ++fmt;
+	}
+      else if (*fmt == '\n')
+	{
+	  /* See whether we have to print a single newline character.  */
+	  if (fmt == startp)
+	    {
+	      iov[niov].iov_base = (char *) startp;
+	      iov[niov++].iov_len = 1;
+	    }
+	  else
+	    /* No, just add it to the rest of the string.  */
+	    ++iov[niov - 1].iov_len;
+
+	  /* Next line, print a tag again.  */
+	  tag_p = 1;
+	  ++fmt;
+	}
+    }
+
+  /* Finally write the result.  */
+  _dl_writev (fd, iov, niov);
+}
+
+
+/* Write to debug file.  */
+void
+_dl_debug_printf (const char *fmt, ...)
+{
+  va_list arg;
+
+  va_start (arg, fmt);
+  _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
+  va_end (arg);
+}
+
+
+/* Write to debug file but don't start with a tag.  */
+void
+_dl_debug_printf_c (const char *fmt, ...)
+{
+  va_list arg;
+
+  va_start (arg, fmt);
+  _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
+  va_end (arg);
+}
+
+
+/* Write the given file descriptor.  */
+void
+_dl_dprintf (int fd, const char *fmt, ...)
+{
+  va_list arg;
+
+  va_start (arg, fmt);
+  _dl_debug_vdprintf (fd, 0, fmt, arg);
+  va_end (arg);
+}
+
+
+/* Test whether given NAME matches any of the names of the given object.  */
+int
+internal_function
+_dl_name_match_p (const char *name, const struct link_map *map)
+{
+  if (strcmp (name, map->l_name) == 0)
+    return 1;
+
+  struct libname_list *runp = map->l_libname;
+
+  while (runp != NULL)
+    if (strcmp (name, runp->name) == 0)
+      return 1;
+    else
+      runp = runp->next;
+
+  return 0;
+}
+
+
+unsigned long int
+internal_function
+_dl_higher_prime_number (unsigned long int n)
+{
+  /* These are primes that are near, but slightly smaller than, a
+     power of two.  */
+  static const uint32_t primes[] = {
+    UINT32_C (7),
+    UINT32_C (13),
+    UINT32_C (31),
+    UINT32_C (61),
+    UINT32_C (127),
+    UINT32_C (251),
+    UINT32_C (509),
+    UINT32_C (1021),
+    UINT32_C (2039),
+    UINT32_C (4093),
+    UINT32_C (8191),
+    UINT32_C (16381),
+    UINT32_C (32749),
+    UINT32_C (65521),
+    UINT32_C (131071),
+    UINT32_C (262139),
+    UINT32_C (524287),
+    UINT32_C (1048573),
+    UINT32_C (2097143),
+    UINT32_C (4194301),
+    UINT32_C (8388593),
+    UINT32_C (16777213),
+    UINT32_C (33554393),
+    UINT32_C (67108859),
+    UINT32_C (134217689),
+    UINT32_C (268435399),
+    UINT32_C (536870909),
+    UINT32_C (1073741789),
+    UINT32_C (2147483647),
+				       /* 4294967291L */
+    UINT32_C (2147483647) + UINT32_C (2147483644)
+  };
+
+  const uint32_t *low = &primes[0];
+  const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
+
+  while (low != high)
+    {
+      const uint32_t *mid = low + (high - low) / 2;
+      if (n > *mid)
+       low = mid + 1;
+      else
+       high = mid;
+    }
+
+#if 0
+  /* If we've run out of primes, abort.  */
+  if (n > *low)
+    {
+      fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
+      abort ();
+    }
+#endif
+
+  return *low;
+}
diff --git a/REORG.TODO/elf/dl-object.c b/REORG.TODO/elf/dl-object.c
new file mode 100644
index 0000000000..4c43235148
--- /dev/null
+++ b/REORG.TODO/elf/dl-object.c
@@ -0,0 +1,229 @@
+/* Storage management for the chain of loaded shared objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+
+#include <assert.h>
+
+
+/* Add the new link_map NEW to the end of the namespace list.  */
+void
+internal_function
+_dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
+{
+  /* We modify the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
+  if (GL(dl_ns)[nsid]._ns_loaded != NULL)
+    {
+      struct link_map *l = GL(dl_ns)[nsid]._ns_loaded;
+      while (l->l_next != NULL)
+	l = l->l_next;
+      new->l_prev = l;
+      /* new->l_next = NULL;   Would be necessary but we use calloc.  */
+      l->l_next = new;
+    }
+  else
+    GL(dl_ns)[nsid]._ns_loaded = new;
+  ++GL(dl_ns)[nsid]._ns_nloaded;
+  new->l_serial = GL(dl_load_adds);
+  ++GL(dl_load_adds);
+
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+}
+
+
+/* Allocate a `struct link_map' for a new object being loaded,
+   and enter it into the _dl_loaded list.  */
+struct link_map *
+internal_function
+_dl_new_object (char *realname, const char *libname, int type,
+		struct link_map *loader, int mode, Lmid_t nsid)
+{
+  size_t libname_len = strlen (libname) + 1;
+  struct link_map *new;
+  struct libname_list *newname;
+#ifdef SHARED
+  /* We create the map for the executable before we know whether we have
+     auditing libraries and if yes, how many.  Assume the worst.  */
+  unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
+					    ? DL_NNS : 0);
+  size_t audit_space = naudit * sizeof (new->l_audit[0]);
+#else
+# define audit_space 0
+#endif
+
+  new = (struct link_map *) calloc (sizeof (*new) + audit_space
+				    + sizeof (struct link_map *)
+				    + sizeof (*newname) + libname_len, 1);
+  if (new == NULL)
+    return NULL;
+
+  new->l_real = new;
+  new->l_symbolic_searchlist.r_list = (struct link_map **) ((char *) (new + 1)
+							    + audit_space);
+
+  new->l_libname = newname
+    = (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1);
+  newname->name = (char *) memcpy (newname + 1, libname, libname_len);
+  /* newname->next = NULL;	We use calloc therefore not necessary.  */
+  newname->dont_free = 1;
+
+  /* When we create the executable link map, or a VDSO link map, we start
+     with "" for the l_name. In these cases "" points to ld.so rodata
+     and won't get dumped during core file generation. Therefore to assist
+     gdb and to create more self-contained core files we adjust l_name to
+     point at the newly allocated copy (which will get dumped) instead of
+     the ld.so rodata copy.  */
+  new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
+  new->l_type = type;
+  /* If we set the bit now since we know it is never used we avoid
+     dirtying the cache line later.  */
+  if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0)
+    new->l_used = 1;
+  new->l_loader = loader;
+#if NO_TLS_OFFSET != 0
+  new->l_tls_offset = NO_TLS_OFFSET;
+#endif
+  new->l_ns = nsid;
+
+#ifdef SHARED
+  for (unsigned int cnt = 0; cnt < naudit; ++cnt)
+    {
+      new->l_audit[cnt].cookie = (uintptr_t) new;
+      /* new->l_audit[cnt].bindflags = 0; */
+    }
+#endif
+
+  /* new->l_global = 0;	We use calloc therefore not necessary.  */
+
+  /* Use the 'l_scope_mem' array by default for the 'l_scope'
+     information.  If we need more entries we will allocate a large
+     array dynamically.  */
+  new->l_scope = new->l_scope_mem;
+  new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
+
+  /* Counter for the scopes we have to handle.  */
+  int idx = 0;
+
+  if (GL(dl_ns)[nsid]._ns_loaded != NULL)
+    /* Add the global scope.  */
+    new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist;
+
+  /* If we have no loader the new object acts as it.  */
+  if (loader == NULL)
+    loader = new;
+  else
+    /* Determine the local scope.  */
+    while (loader->l_loader != NULL)
+      loader = loader->l_loader;
+
+  /* Insert the scope if it isn't the global scope we already added.  */
+  if (idx == 0 || &loader->l_searchlist != new->l_scope[0])
+    {
+      if ((mode & RTLD_DEEPBIND) != 0 && idx != 0)
+	{
+	  new->l_scope[1] = new->l_scope[0];
+	  idx = 0;
+	}
+
+      new->l_scope[idx] = &loader->l_searchlist;
+    }
+
+  new->l_local_scope[0] = &new->l_searchlist;
+
+  /* Don't try to find the origin for the main map which has the name "".  */
+  if (realname[0] != '\0')
+    {
+      size_t realname_len = strlen (realname) + 1;
+      char *origin;
+      char *cp;
+
+      if (realname[0] == '/')
+	{
+	  /* It is an absolute path.  Use it.  But we have to make a
+	     copy since we strip out the trailing slash.  */
+	  cp = origin = (char *) malloc (realname_len);
+	  if (origin == NULL)
+	    {
+	      origin = (char *) -1;
+	      goto out;
+	    }
+	}
+      else
+	{
+	  size_t len = realname_len;
+	  char *result = NULL;
+
+	  /* Get the current directory name.  */
+	  origin = NULL;
+	  do
+	    {
+	      char *new_origin;
+
+	      len += 128;
+	      new_origin = (char *) realloc (origin, len);
+	      if (new_origin == NULL)
+		/* We exit the loop.  Note that result == NULL.  */
+		break;
+	      origin = new_origin;
+	    }
+	  while ((result = __getcwd (origin, len - realname_len)) == NULL
+		 && errno == ERANGE);
+
+	  if (result == NULL)
+	    {
+	      /* We were not able to determine the current directory.
+		 Note that free(origin) is OK if origin == NULL.  */
+	      free (origin);
+	      origin = (char *) -1;
+	      goto out;
+	    }
+
+	  /* Find the end of the path and see whether we have to add a
+	     slash.  We could use rawmemchr but this need not be
+	     fast.  */
+	  cp = (strchr) (origin, '\0');
+	  if (cp[-1] != '/')
+	    *cp++ = '/';
+	}
+
+      /* Add the real file name.  */
+      cp = __mempcpy (cp, realname, realname_len);
+
+      /* Now remove the filename and the slash.  Leave the slash if
+	 the name is something like "/foo".  */
+      do
+	--cp;
+      while (*cp != '/');
+
+      if (cp == origin)
+	/* Keep the only slash which is the first character.  */
+	++cp;
+      *cp = '\0';
+
+    out:
+      new->l_origin = origin;
+    }
+
+  return new;
+}
diff --git a/REORG.TODO/elf/dl-open.c b/REORG.TODO/elf/dl-open.c
new file mode 100644
index 0000000000..cec54db413
--- /dev/null
+++ b/REORG.TODO/elf/dl-open.c
@@ -0,0 +1,737 @@
+/* Load a shared object at runtime, relocate it, and run its initializer.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>		/* Check whether MAP_COPY is defined.  */
+#include <sys/param.h>
+#include <libc-lock.h>
+#include <ldsodefs.h>
+#include <caller.h>
+#include <sysdep-cancel.h>
+#include <tls.h>
+#include <stap-probe.h>
+#include <atomic.h>
+
+#include <dl-dst.h>
+
+
+extern int __libc_multiple_libcs;	/* Defined in init-first.c.  */
+
+/* We must be careful not to leave us in an inconsistent state.  Thus we
+   catch any error and re-raise it after cleaning up.  */
+
+struct dl_open_args
+{
+  const char *file;
+  int mode;
+  /* This is the caller of the dlopen() function.  */
+  const void *caller_dlopen;
+  /* This is the caller of _dl_open().  */
+  const void *caller_dl_open;
+  struct link_map *map;
+  /* Namespace ID.  */
+  Lmid_t nsid;
+  /* Original parameters to the program and the current environment.  */
+  int argc;
+  char **argv;
+  char **env;
+};
+
+
+static int
+add_to_global (struct link_map *new)
+{
+  struct link_map **new_global;
+  unsigned int to_add = 0;
+  unsigned int cnt;
+
+  /* Count the objects we have to put in the global scope.  */
+  for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
+    if (new->l_searchlist.r_list[cnt]->l_global == 0)
+      ++to_add;
+
+  /* The symbols of the new objects and its dependencies are to be
+     introduced into the global scope that will be used to resolve
+     references from other dynamically-loaded objects.
+
+     The global scope is the searchlist in the main link map.  We
+     extend this list if necessary.  There is one problem though:
+     since this structure was allocated very early (before the libc
+     is loaded) the memory it uses is allocated by the malloc()-stub
+     in the ld.so.  When we come here these functions are not used
+     anymore.  Instead the malloc() implementation of the libc is
+     used.  But this means the block from the main map cannot be used
+     in an realloc() call.  Therefore we allocate a completely new
+     array the first time we have to add something to the locale scope.  */
+
+  struct link_namespaces *ns = &GL(dl_ns)[new->l_ns];
+  if (ns->_ns_global_scope_alloc == 0)
+    {
+      /* This is the first dynamic object given global scope.  */
+      ns->_ns_global_scope_alloc
+	= ns->_ns_main_searchlist->r_nlist + to_add + 8;
+      new_global = (struct link_map **)
+	malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *));
+      if (new_global == NULL)
+	{
+	  ns->_ns_global_scope_alloc = 0;
+	nomem:
+	  _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
+			    N_("cannot extend global scope"));
+	  return 1;
+	}
+
+      /* Copy over the old entries.  */
+      ns->_ns_main_searchlist->r_list
+	= memcpy (new_global, ns->_ns_main_searchlist->r_list,
+		  (ns->_ns_main_searchlist->r_nlist
+		   * sizeof (struct link_map *)));
+    }
+  else if (ns->_ns_main_searchlist->r_nlist + to_add
+	   > ns->_ns_global_scope_alloc)
+    {
+      /* We have to extend the existing array of link maps in the
+	 main map.  */
+      struct link_map **old_global
+	= GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
+      size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
+
+      new_global = (struct link_map **)
+	malloc (new_nalloc * sizeof (struct link_map *));
+      if (new_global == NULL)
+	goto nomem;
+
+      memcpy (new_global, old_global,
+	      ns->_ns_global_scope_alloc * sizeof (struct link_map *));
+
+      ns->_ns_global_scope_alloc = new_nalloc;
+      ns->_ns_main_searchlist->r_list = new_global;
+
+      if (!RTLD_SINGLE_THREAD_P)
+	THREAD_GSCOPE_WAIT ();
+
+      free (old_global);
+    }
+
+  /* Now add the new entries.  */
+  unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
+  for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
+    {
+      struct link_map *map = new->l_searchlist.r_list[cnt];
+
+      if (map->l_global == 0)
+	{
+	  map->l_global = 1;
+	  ns->_ns_main_searchlist->r_list[new_nlist++] = map;
+
+	  /* We modify the global scope.  Report this.  */
+	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
+	    _dl_debug_printf ("\nadd %s [%lu] to global scope\n",
+			      map->l_name, map->l_ns);
+	}
+    }
+  atomic_write_barrier ();
+  ns->_ns_main_searchlist->r_nlist = new_nlist;
+
+  return 0;
+}
+
+/* Search link maps in all namespaces for the DSO that contains the object at
+   address ADDR.  Returns the pointer to the link map of the matching DSO, or
+   NULL if a match is not found.  */
+struct link_map *
+internal_function
+_dl_find_dso_for_object (const ElfW(Addr) addr)
+{
+  struct link_map *l;
+
+  /* Find the highest-addressed object that ADDR is not below.  */
+  for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
+    for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
+      if (addr >= l->l_map_start && addr < l->l_map_end
+	  && (l->l_contiguous
+	      || _dl_addr_inside_object (l, (ElfW(Addr)) addr)))
+	{
+	  assert (ns == l->l_ns);
+	  return l;
+	}
+  return NULL;
+}
+rtld_hidden_def (_dl_find_dso_for_object);
+
+static void
+dl_open_worker (void *a)
+{
+  struct dl_open_args *args = a;
+  const char *file = args->file;
+  int mode = args->mode;
+  struct link_map *call_map = NULL;
+
+  /* Check whether _dl_open() has been called from a valid DSO.  */
+  if (__check_caller (args->caller_dl_open,
+		      allow_libc|allow_libdl|allow_ldso) != 0)
+    _dl_signal_error (0, "dlopen", NULL, N_("invalid caller"));
+
+  /* Determine the caller's map if necessary.  This is needed in case
+     we have a DST, when we don't know the namespace ID we have to put
+     the new object in, or when the file name has no path in which
+     case we need to look along the RUNPATH/RPATH of the caller.  */
+  const char *dst = strchr (file, '$');
+  if (dst != NULL || args->nsid == __LM_ID_CALLER
+      || strchr (file, '/') == NULL)
+    {
+      const void *caller_dlopen = args->caller_dlopen;
+
+      /* We have to find out from which object the caller is calling.
+	 By default we assume this is the main application.  */
+      call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+      struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
+
+      if (l)
+	call_map = l;
+
+      if (args->nsid == __LM_ID_CALLER)
+	args->nsid = call_map->l_ns;
+    }
+
+  /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
+     may not be true if this is a recursive call to dlopen.  */
+  _dl_debug_initialize (0, args->nsid);
+
+  /* Load the named object.  */
+  struct link_map *new;
+  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
+				    mode | __RTLD_CALLMAP, args->nsid);
+
+  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
+     set and the object is not already loaded.  */
+  if (new == NULL)
+    {
+      assert (mode & RTLD_NOLOAD);
+      return;
+    }
+
+  /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
+     Do this early so that we don't skip marking the object if it was
+     already loaded.  */
+  if (__glibc_unlikely (mode & RTLD_NODELETE))
+    new->l_flags_1 |= DF_1_NODELETE;
+
+  if (__glibc_unlikely (mode & __RTLD_SPROF))
+    /* This happens only if we load a DSO for 'sprof'.  */
+    return;
+
+  /* This object is directly loaded.  */
+  ++new->l_direct_opencount;
+
+  /* It was already open.  */
+  if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
+    {
+      /* Let the user know about the opencount.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+	_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+			  new->l_name, new->l_ns, new->l_direct_opencount);
+
+      /* If the user requested the object to be in the global namespace
+	 but it is not so far, add it now.  */
+      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
+	(void) add_to_global (new);
+
+      assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
+
+      return;
+    }
+
+  /* Load that object's dependencies.  */
+  _dl_map_object_deps (new, NULL, 0, 0,
+		       mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
+
+  /* So far, so good.  Now check the versions.  */
+  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+    if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
+      (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
+				     0, 0);
+
+#ifdef SHARED
+  /* Auditing checkpoint: we have added all objects.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+    {
+      struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
+      /* Do not call the functions for any auditing object.  */
+      if (head->l_auditing == 0)
+	{
+	  struct audit_ifaces *afct = GLRO(dl_audit);
+	  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	    {
+	      if (afct->activity != NULL)
+		afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+	      afct = afct->next;
+	    }
+	}
+    }
+#endif
+
+  /* Notify the debugger all new objects are now ready to go.  */
+  struct r_debug *r = _dl_debug_initialize (0, args->nsid);
+  r->r_state = RT_CONSISTENT;
+  _dl_debug_state ();
+  LIBC_PROBE (map_complete, 3, args->nsid, r, new);
+
+  /* Print scope information.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
+    _dl_show_scope (new, 0);
+
+  /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */
+  int reloc_mode = mode & __RTLD_AUDIT;
+  if (GLRO(dl_lazy))
+    reloc_mode |= mode & RTLD_LAZY;
+
+  /* Sort the objects by dependency for the relocation process.  This
+     allows IFUNC relocations to work and it also means copy
+     relocation of dependencies are if necessary overwritten.  */
+  size_t nmaps = 0;
+  struct link_map *l = new;
+  do
+    {
+      if (! l->l_real->l_relocated)
+	++nmaps;
+      l = l->l_next;
+    }
+  while (l != NULL);
+  struct link_map *maps[nmaps];
+  nmaps = 0;
+  l = new;
+  do
+    {
+      if (! l->l_real->l_relocated)
+	maps[nmaps++] = l;
+      l = l->l_next;
+    }
+  while (l != NULL);
+  if (nmaps > 1)
+    {
+      uint16_t seen[nmaps];
+      memset (seen, '\0', sizeof (seen));
+      size_t i = 0;
+      while (1)
+	{
+	  ++seen[i];
+	  struct link_map *thisp = maps[i];
+
+	  /* Find the last object in the list for which the current one is
+	     a dependency and move the current object behind the object
+	     with the dependency.  */
+	  size_t k = nmaps - 1;
+	  while (k > i)
+	    {
+	      struct link_map **runp = maps[k]->l_initfini;
+	      if (runp != NULL)
+		/* Look through the dependencies of the object.  */
+		while (*runp != NULL)
+		  if (__glibc_unlikely (*runp++ == thisp))
+		    {
+		      /* Move the current object to the back past the last
+			 object with it as the dependency.  */
+		      memmove (&maps[i], &maps[i + 1],
+			       (k - i) * sizeof (maps[0]));
+		      maps[k] = thisp;
+
+		      if (seen[i + 1] > nmaps - i)
+			{
+			  ++i;
+			  goto next_clear;
+			}
+
+		      uint16_t this_seen = seen[i];
+		      memmove (&seen[i], &seen[i + 1],
+			       (k - i) * sizeof (seen[0]));
+		      seen[k] = this_seen;
+
+		      goto next;
+		    }
+
+	      --k;
+	    }
+
+	  if (++i == nmaps)
+	    break;
+	next_clear:
+	  memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
+	next:;
+	}
+    }
+
+  int relocation_in_progress = 0;
+
+  for (size_t i = nmaps; i-- > 0; )
+    {
+      l = maps[i];
+
+      if (! relocation_in_progress)
+	{
+	  /* Notify the debugger that relocations are about to happen.  */
+	  LIBC_PROBE (reloc_start, 2, args->nsid, r);
+	  relocation_in_progress = 1;
+	}
+
+#ifdef SHARED
+      if (__glibc_unlikely (GLRO(dl_profile) != NULL))
+	{
+	  /* If this here is the shared object which we want to profile
+	     make sure the profile is started.  We can find out whether
+	     this is necessary or not by observing the `_dl_profile_map'
+	     variable.  If it was NULL but is not NULL afterwards we must
+	     start the profiling.  */
+	  struct link_map *old_profile_map = GL(dl_profile_map);
+
+	  _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
+
+	  if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
+	    {
+	      /* We must prepare the profiling.  */
+	      _dl_start_profile ();
+
+	      /* Prevent unloading the object.  */
+	      GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
+	    }
+	}
+      else
+#endif
+	_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
+    }
+
+  /* If the file is not loaded now as a dependency, add the search
+     list of the newly loaded object to the scope.  */
+  bool any_tls = false;
+  unsigned int first_static_tls = new->l_searchlist.r_nlist;
+  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+    {
+      struct link_map *imap = new->l_searchlist.r_list[i];
+      int from_scope = 0;
+
+      /* If the initializer has been called already, the object has
+	 not been loaded here and now.  */
+      if (imap->l_init_called && imap->l_type == lt_loaded)
+	{
+	  struct r_scope_elem **runp = imap->l_scope;
+	  size_t cnt = 0;
+
+	  while (*runp != NULL)
+	    {
+	      if (*runp == &new->l_searchlist)
+		break;
+	      ++cnt;
+	      ++runp;
+	    }
+
+	  if (*runp != NULL)
+	    /* Avoid duplicates.  */
+	    continue;
+
+	  if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
+	    {
+	      /* The 'r_scope' array is too small.  Allocate a new one
+		 dynamically.  */
+	      size_t new_size;
+	      struct r_scope_elem **newp;
+
+#define SCOPE_ELEMS(imap) \
+  (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
+
+	      if (imap->l_scope != imap->l_scope_mem
+		  && imap->l_scope_max < SCOPE_ELEMS (imap))
+		{
+		  new_size = SCOPE_ELEMS (imap);
+		  newp = imap->l_scope_mem;
+		}
+	      else
+		{
+		  new_size = imap->l_scope_max * 2;
+		  newp = (struct r_scope_elem **)
+		    malloc (new_size * sizeof (struct r_scope_elem *));
+		  if (newp == NULL)
+		    _dl_signal_error (ENOMEM, "dlopen", NULL,
+				      N_("cannot create scope list"));
+		}
+
+	      memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
+	      struct r_scope_elem **old = imap->l_scope;
+
+	      imap->l_scope = newp;
+
+	      if (old != imap->l_scope_mem)
+		_dl_scope_free (old);
+
+	      imap->l_scope_max = new_size;
+	    }
+
+	  /* First terminate the extended list.  Otherwise a thread
+	     might use the new last element and then use the garbage
+	     at offset IDX+1.  */
+	  imap->l_scope[cnt + 1] = NULL;
+	  atomic_write_barrier ();
+	  imap->l_scope[cnt] = &new->l_searchlist;
+
+	  /* Print only new scope information.  */
+	  from_scope = cnt;
+	}
+      /* Only add TLS memory if this object is loaded now and
+	 therefore is not yet initialized.  */
+      else if (! imap->l_init_called
+	       /* Only if the module defines thread local data.  */
+	       && __builtin_expect (imap->l_tls_blocksize > 0, 0))
+	{
+	  /* Now that we know the object is loaded successfully add
+	     modules containing TLS data to the slot info table.  We
+	     might have to increase its size.  */
+	  _dl_add_to_slotinfo (imap);
+
+	  if (imap->l_need_tls_init
+	      && first_static_tls == new->l_searchlist.r_nlist)
+	    first_static_tls = i;
+
+	  /* We have to bump the generation counter.  */
+	  any_tls = true;
+	}
+
+      /* Print scope information.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
+	_dl_show_scope (imap, from_scope);
+    }
+
+  /* Bump the generation number if necessary.  */
+  if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
+    _dl_fatal_printf (N_("\
+TLS generation counter wrapped!  Please report this."));
+
+  /* We need a second pass for static tls data, because _dl_update_slotinfo
+     must not be run while calls to _dl_add_to_slotinfo are still pending.  */
+  for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
+    {
+      struct link_map *imap = new->l_searchlist.r_list[i];
+
+      if (imap->l_need_tls_init
+	  && ! imap->l_init_called
+	  && imap->l_tls_blocksize > 0)
+	{
+	  /* For static TLS we have to allocate the memory here and
+	     now, but we can delay updating the DTV.  */
+	  imap->l_need_tls_init = 0;
+#ifdef SHARED
+	  /* Update the slot information data for at least the
+	     generation of the DSO we are allocating data for.  */
+	  _dl_update_slotinfo (imap->l_tls_modid);
+#endif
+
+	  GL(dl_init_static_tls) (imap);
+	  assert (imap->l_need_tls_init == 0);
+	}
+    }
+
+  /* Notify the debugger all new objects have been relocated.  */
+  if (relocation_in_progress)
+    LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
+
+#ifndef SHARED
+  DL_STATIC_INIT (new);
+#endif
+
+  /* Run the initializer functions of new objects.  */
+  _dl_init (new, args->argc, args->argv, args->env);
+
+  /* Now we can make the new map available in the global scope.  */
+  if (mode & RTLD_GLOBAL)
+    /* Move the object in the global namespace.  */
+    if (add_to_global (new) != 0)
+      /* It failed.  */
+      return;
+
+#ifndef SHARED
+  /* We must be the static _dl_open in libc.a.  A static program that
+     has loaded a dynamic object now has competition.  */
+  __libc_multiple_libcs = 1;
+#endif
+
+  /* Let the user know about the opencount.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+    _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+		      new->l_name, new->l_ns, new->l_direct_opencount);
+}
+
+
+void *
+_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+	  int argc, char *argv[], char *env[])
+{
+  if ((mode & RTLD_BINDING_MASK) == 0)
+    /* One of the flags must be set.  */
+    _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
+
+  /* Make sure we are alone.  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  if (__glibc_unlikely (nsid == LM_ID_NEWLM))
+    {
+      /* Find a new namespace.  */
+      for (nsid = 1; DL_NNS > 1 && nsid < GL(dl_nns); ++nsid)
+	if (GL(dl_ns)[nsid]._ns_loaded == NULL)
+	  break;
+
+      if (__glibc_unlikely (nsid == DL_NNS))
+	{
+	  /* No more namespace available.  */
+	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+	  _dl_signal_error (EINVAL, file, NULL, N_("\
+no more namespaces available for dlmopen()"));
+	}
+      else if (nsid == GL(dl_nns))
+	{
+	  __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+	  ++GL(dl_nns);
+	}
+
+      _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
+    }
+  /* Never allow loading a DSO in a namespace which is empty.  Such
+     direct placements is only causing problems.  Also don't allow
+     loading into a namespace used for auditing.  */
+  else if (__glibc_unlikely (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER)
+	   && (__glibc_unlikely (nsid < 0 || nsid >= GL(dl_nns))
+	       /* This prevents the [NSID] index expressions from being
+		  evaluated, so the compiler won't think that we are
+		  accessing an invalid index here in the !SHARED case where
+		  DL_NNS is 1 and so any NSID != 0 is invalid.  */
+	       || DL_NNS == 1
+	       || GL(dl_ns)[nsid]._ns_nloaded == 0
+	       || GL(dl_ns)[nsid]._ns_loaded->l_auditing))
+    _dl_signal_error (EINVAL, file, NULL,
+		      N_("invalid target namespace in dlmopen()"));
+
+  struct dl_open_args args;
+  args.file = file;
+  args.mode = mode;
+  args.caller_dlopen = caller_dlopen;
+  args.caller_dl_open = RETURN_ADDRESS (0);
+  args.map = NULL;
+  args.nsid = nsid;
+  args.argc = argc;
+  args.argv = argv;
+  args.env = env;
+
+  const char *objname;
+  const char *errstring;
+  bool malloced;
+  int errcode = _dl_catch_error (&objname, &errstring, &malloced,
+				 dl_open_worker, &args);
+
+#if defined USE_LDCONFIG && !defined MAP_COPY
+  /* We must unmap the cache file.  */
+  _dl_unload_cache ();
+#endif
+
+  /* See if an error occurred during loading.  */
+  if (__glibc_unlikely (errstring != NULL))
+    {
+      /* Remove the object from memory.  It may be in an inconsistent
+	 state if relocation failed, for example.  */
+      if (args.map)
+	{
+	  /* Maybe some of the modules which were loaded use TLS.
+	     Since it will be removed in the following _dl_close call
+	     we have to mark the dtv array as having gaps to fill the
+	     holes.  This is a pessimistic assumption which won't hurt
+	     if not true.  There is no need to do this when we are
+	     loading the auditing DSOs since TLS has not yet been set
+	     up.  */
+	  if ((mode & __RTLD_AUDIT) == 0)
+	    GL(dl_tls_dtv_gaps) = true;
+
+	  _dl_close_worker (args.map, true);
+	}
+
+      assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
+
+      /* Release the lock.  */
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+      /* Make a local copy of the error string so that we can release the
+	 memory allocated for it.  */
+      size_t len_errstring = strlen (errstring) + 1;
+      char *local_errstring;
+      if (objname == errstring + len_errstring)
+	{
+	  size_t total_len = len_errstring + strlen (objname) + 1;
+	  local_errstring = alloca (total_len);
+	  memcpy (local_errstring, errstring, total_len);
+	  objname = local_errstring + len_errstring;
+	}
+      else
+	{
+	  local_errstring = alloca (len_errstring);
+	  memcpy (local_errstring, errstring, len_errstring);
+	}
+
+      if (malloced)
+	free ((char *) errstring);
+
+      /* Reraise the error.  */
+      _dl_signal_error (errcode, objname, NULL, local_errstring);
+    }
+
+  assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
+
+  /* Release the lock.  */
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+  return args.map;
+}
+
+
+void
+_dl_show_scope (struct link_map *l, int from)
+{
+  _dl_debug_printf ("object=%s [%lu]\n",
+		    DSO_FILENAME (l->l_name), l->l_ns);
+  if (l->l_scope != NULL)
+    for (int scope_cnt = from; l->l_scope[scope_cnt] != NULL; ++scope_cnt)
+      {
+	_dl_debug_printf (" scope %u:", scope_cnt);
+
+	for (unsigned int cnt = 0; cnt < l->l_scope[scope_cnt]->r_nlist; ++cnt)
+	  if (*l->l_scope[scope_cnt]->r_list[cnt]->l_name)
+	    _dl_debug_printf_c (" %s",
+				l->l_scope[scope_cnt]->r_list[cnt]->l_name);
+	  else
+	    _dl_debug_printf_c (" %s", RTLD_PROGNAME);
+
+	_dl_debug_printf_c ("\n");
+      }
+  else
+    _dl_debug_printf (" no scope\n");
+  _dl_debug_printf ("\n");
+}
diff --git a/REORG.TODO/elf/dl-origin.c b/REORG.TODO/elf/dl-origin.c
new file mode 100644
index 0000000000..1e44272a8e
--- /dev/null
+++ b/REORG.TODO/elf/dl-origin.c
@@ -0,0 +1,50 @@
+/* Find path of executable.
+   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <ldsodefs.h>
+
+#include <dl-dst.h>
+
+
+const char *
+_dl_get_origin (void)
+{
+  char *result = (char *) -1;
+  /* We use the environment variable LD_ORIGIN_PATH.  If it is set make
+     a copy and strip out trailing slashes.  */
+  if (GLRO(dl_origin_path) != NULL)
+    {
+      size_t len = strlen (GLRO(dl_origin_path));
+      result = (char *) malloc (len + 1);
+      if (result == NULL)
+	result = (char *) -1;
+      else
+	{
+	  char *cp = __mempcpy (result, GLRO(dl_origin_path), len);
+	  while (cp > result + 1 && cp[-1] == '/')
+	    --cp;
+	  *cp = '\0';
+	}
+    }
+
+  return result;
+}
diff --git a/REORG.TODO/elf/dl-profile.c b/REORG.TODO/elf/dl-profile.c
new file mode 100644
index 0000000000..a4f11089a1
--- /dev/null
+++ b/REORG.TODO/elf/dl-profile.c
@@ -0,0 +1,596 @@
+/* Profiling of shared libraries.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+   Based on the BSD mcount implementation.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <ldsodefs.h>
+#include <sys/gmon.h>
+#include <sys/gmon_out.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <atomic.h>
+
+/* The LD_PROFILE feature has to be implemented different to the
+   normal profiling using the gmon/ functions.  The problem is that an
+   arbitrary amount of processes simulataneously can be run using
+   profiling and all write the results in the same file.  To provide
+   this mechanism one could implement a complicated mechanism to merge
+   the content of two profiling runs or one could extend the file
+   format to allow more than one data set.  For the second solution we
+   would have the problem that the file can grow in size beyond any
+   limit and both solutions have the problem that the concurrency of
+   writing the results is a big problem.
+
+   Another much simpler method is to use mmap to map the same file in
+   all using programs and modify the data in the mmap'ed area and so
+   also automatically on the disk.  Using the MAP_SHARED option of
+   mmap(2) this can be done without big problems in more than one
+   file.
+
+   This approach is very different from the normal profiling.  We have
+   to use the profiling data in exactly the way they are expected to
+   be written to disk.  But the normal format used by gprof is not usable
+   to do this.  It is optimized for size.  It writes the tags as single
+   bytes but this means that the following 32/64 bit values are
+   unaligned.
+
+   Therefore we use a new format.  This will look like this
+
+					0  1  2  3	<- byte is 32 bit word
+	0000				g  m  o  n
+	0004				*version*	<- GMON_SHOBJ_VERSION
+	0008				00 00 00 00
+	000c				00 00 00 00
+	0010				00 00 00 00
+
+	0014				*tag*		<- GMON_TAG_TIME_HIST
+	0018				?? ?? ?? ??
+					?? ?? ?? ??	<- 32/64 bit LowPC
+	0018+A				?? ?? ?? ??
+					?? ?? ?? ??	<- 32/64 bit HighPC
+	0018+2*A			*histsize*
+	001c+2*A			*profrate*
+	0020+2*A			s  e  c  o
+	0024+2*A			n  d  s  \0
+	0028+2*A			\0 \0 \0 \0
+	002c+2*A			\0 \0 \0
+	002f+2*A			s
+
+	0030+2*A			?? ?? ?? ??	<- Count data
+	...				...
+	0030+2*A+K			?? ?? ?? ??
+
+	0030+2*A+K			*tag*		<- GMON_TAG_CG_ARC
+	0034+2*A+K			*lastused*
+	0038+2*A+K			?? ?? ?? ??
+					?? ?? ?? ??	<- FromPC#1
+	0038+3*A+K			?? ?? ?? ??
+					?? ?? ?? ??	<- ToPC#1
+	0038+4*A+K			?? ?? ?? ??	<- Count#1
+	...				...		   ...
+	0038+(2*(CN-1)+2)*A+(CN-1)*4+K	?? ?? ?? ??
+					?? ?? ?? ??	<- FromPC#CGN
+	0038+(2*(CN-1)+3)*A+(CN-1)*4+K	?? ?? ?? ??
+					?? ?? ?? ??	<- ToPC#CGN
+	0038+(2*CN+2)*A+(CN-1)*4+K	?? ?? ?? ??	<- Count#CGN
+
+   We put (for now?) no basic block information in the file since this would
+   introduce rase conditions among all the processes who want to write them.
+
+   `K' is the number of count entries which is computed as
+
+ 		textsize / HISTFRACTION
+
+   `CG' in the above table is the number of call graph arcs.  Normally,
+   the table is sparse and the profiling code writes out only the those
+   entries which are really used in the program run.  But since we must
+   not extend this table (the profiling file) we'll keep them all here.
+   So CN can be executed in advance as
+
+		MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS
+
+   Now the remaining question is: how to build the data structures we can
+   work with from this data.  We need the from set and must associate the
+   froms with all the associated tos.  We will do this by constructing this
+   data structures at the program start.  To do this we'll simply visit all
+   entries in the call graph table and add it to the appropriate list.  */
+
+extern int __profile_frequency (void);
+libc_hidden_proto (__profile_frequency)
+
+/* We define a special type to address the elements of the arc table.
+   This is basically the `gmon_cg_arc_record' format but it includes
+   the room for the tag and it uses real types.  */
+struct here_cg_arc_record
+  {
+    uintptr_t from_pc;
+    uintptr_t self_pc;
+    /* The count field is atomically incremented in _dl_mcount, which
+       requires it to be properly aligned for its type, and for this
+       alignment to be visible to the compiler.  The amount of data
+       before an array of this structure is calculated as
+       expected_size in _dl_start_profile.  Everything in that
+       calculation is a multiple of 4 bytes (in the case of
+       kcountsize, because it is derived from a subtraction of
+       page-aligned values, and the corresponding calculation in
+       __monstartup also ensures it is at least a multiple of the size
+       of u_long), so all copies of this field do in fact have the
+       appropriate alignment.  */
+    uint32_t count __attribute__ ((aligned (__alignof__ (uint32_t))));
+  } __attribute__ ((packed));
+
+static struct here_cg_arc_record *data;
+
+/* Nonzero if profiling is under way.  */
+static int running;
+
+/* This is the number of entry which have been incorporated in the toset.  */
+static uint32_t narcs;
+/* This is a pointer to the object representing the number of entries
+   currently in the mmaped file.  At no point of time this has to be the
+   same as NARCS.  If it is equal all entries from the file are in our
+   lists.  */
+static volatile uint32_t *narcsp;
+
+
+struct here_fromstruct
+  {
+    struct here_cg_arc_record volatile *here;
+    uint16_t link;
+  };
+
+static volatile uint16_t *tos;
+
+static struct here_fromstruct *froms;
+static uint32_t fromlimit;
+static volatile uint32_t fromidx;
+
+static uintptr_t lowpc;
+static size_t textsize;
+static unsigned int log_hashfraction;
+
+
+
+/* Set up profiling data to profile object desribed by MAP.  The output
+   file is found (or created) in OUTPUT_DIR.  */
+void
+internal_function
+_dl_start_profile (void)
+{
+  char *filename;
+  int fd;
+  struct stat64 st;
+  const ElfW(Phdr) *ph;
+  ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
+  ElfW(Addr) mapend = 0;
+  char *hist, *cp;
+  size_t idx;
+  size_t tossize;
+  size_t fromssize;
+  uintptr_t highpc;
+  uint16_t *kcount;
+  size_t kcountsize;
+  struct gmon_hdr *addr = NULL;
+  off_t expected_size;
+  /* See profil(2) where this is described.  */
+  int s_scale;
+#define SCALE_1_TO_1	0x10000L
+  const char *errstr = NULL;
+
+  /* Compute the size of the sections which contain program code.  */
+  for (ph = GL(dl_profile_map)->l_phdr;
+       ph < &GL(dl_profile_map)->l_phdr[GL(dl_profile_map)->l_phnum]; ++ph)
+    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
+      {
+	ElfW(Addr) start = (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1));
+	ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
+			  & ~(GLRO(dl_pagesize) - 1));
+
+	if (start < mapstart)
+	  mapstart = start;
+	if (end > mapend)
+	  mapend = end;
+      }
+
+  /* Now we can compute the size of the profiling data.  This is done
+     with the same formulars as in `monstartup' (see gmon.c).  */
+  running = 0;
+  lowpc = ROUNDDOWN (mapstart + GL(dl_profile_map)->l_addr,
+		     HISTFRACTION * sizeof (HISTCOUNTER));
+  highpc = ROUNDUP (mapend + GL(dl_profile_map)->l_addr,
+		    HISTFRACTION * sizeof (HISTCOUNTER));
+  textsize = highpc - lowpc;
+  kcountsize = textsize / HISTFRACTION;
+  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
+    {
+      /* If HASHFRACTION is a power of two, mcount can use shifting
+	 instead of integer division.  Precompute shift amount.
+
+	 This is a constant but the compiler cannot compile the
+	 expression away since the __ffs implementation is not known
+	 to the compiler.  Help the compiler by precomputing the
+	 usual cases.  */
+      assert (HASHFRACTION == 2);
+
+      if (sizeof (*froms) == 8)
+	log_hashfraction = 4;
+      else if (sizeof (*froms) == 16)
+	log_hashfraction = 5;
+      else
+	log_hashfraction = __ffs (HASHFRACTION * sizeof (*froms)) - 1;
+    }
+  else
+    log_hashfraction = -1;
+  tossize = textsize / HASHFRACTION;
+  fromlimit = textsize * ARCDENSITY / 100;
+  if (fromlimit < MINARCS)
+    fromlimit = MINARCS;
+  if (fromlimit > MAXARCS)
+    fromlimit = MAXARCS;
+  fromssize = fromlimit * sizeof (struct here_fromstruct);
+
+  expected_size = (sizeof (struct gmon_hdr)
+		   + 4 + sizeof (struct gmon_hist_hdr) + kcountsize
+		   + 4 + 4 + fromssize * sizeof (struct here_cg_arc_record));
+
+  /* Create the gmon_hdr we expect or write.  */
+  struct real_gmon_hdr
+  {
+    char cookie[4];
+    int32_t version;
+    char spare[3 * 4];
+  } gmon_hdr;
+  if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr)
+      || (offsetof (struct real_gmon_hdr, cookie)
+	  != offsetof (struct gmon_hdr, cookie))
+      || (offsetof (struct real_gmon_hdr, version)
+	  != offsetof (struct gmon_hdr, version)))
+    abort ();
+
+  memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
+  gmon_hdr.version = GMON_SHOBJ_VERSION;
+  memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare));
+
+  /* Create the hist_hdr we expect or write.  */
+  struct real_gmon_hist_hdr
+  {
+    char *low_pc;
+    char *high_pc;
+    int32_t hist_size;
+    int32_t prof_rate;
+    char dimen[15];
+    char dimen_abbrev;
+  } hist_hdr;
+  if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr)
+      || (offsetof (struct real_gmon_hist_hdr, low_pc)
+	  != offsetof (struct gmon_hist_hdr, low_pc))
+      || (offsetof (struct real_gmon_hist_hdr, high_pc)
+	  != offsetof (struct gmon_hist_hdr, high_pc))
+      || (offsetof (struct real_gmon_hist_hdr, hist_size)
+	  != offsetof (struct gmon_hist_hdr, hist_size))
+      || (offsetof (struct real_gmon_hist_hdr, prof_rate)
+	  != offsetof (struct gmon_hist_hdr, prof_rate))
+      || (offsetof (struct real_gmon_hist_hdr, dimen)
+	  != offsetof (struct gmon_hist_hdr, dimen))
+      || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev)
+	  != offsetof (struct gmon_hist_hdr, dimen_abbrev)))
+    abort ();
+
+  hist_hdr.low_pc = (char *) mapstart;
+  hist_hdr.high_pc = (char *) mapend;
+  hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER);
+  hist_hdr.prof_rate = __profile_frequency ();
+  if (sizeof (hist_hdr.dimen) >= sizeof ("seconds"))
+    {
+      memcpy (hist_hdr.dimen, "seconds", sizeof ("seconds"));
+      memset (hist_hdr.dimen + sizeof ("seconds"), '\0',
+	      sizeof (hist_hdr.dimen) - sizeof ("seconds"));
+    }
+  else
+    strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
+  hist_hdr.dimen_abbrev = 's';
+
+  /* First determine the output name.  We write in the directory
+     OUTPUT_DIR and the name is composed from the shared objects
+     soname (or the file name) and the ending ".profile".  */
+  filename = (char *) alloca (strlen (GLRO(dl_profile_output)) + 1
+			      + strlen (GLRO(dl_profile)) + sizeof ".profile");
+  cp = __stpcpy (filename, GLRO(dl_profile_output));
+  *cp++ = '/';
+  __stpcpy (__stpcpy (cp, GLRO(dl_profile)), ".profile");
+
+  fd = __open (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE);
+  if (fd == -1)
+    {
+      char buf[400];
+      int errnum;
+
+      /* We cannot write the profiling data so don't do anything.  */
+      errstr = "%s: cannot open file: %s\n";
+    print_error:
+      errnum = errno;
+      if (fd != -1)
+	__close (fd);
+      _dl_error_printf (errstr, filename,
+			__strerror_r (errnum, buf, sizeof buf));
+      return;
+    }
+
+  if (__fxstat64 (_STAT_VER, fd, &st) < 0 || !S_ISREG (st.st_mode))
+    {
+      /* Not stat'able or not a regular file => don't use it.  */
+      errstr = "%s: cannot stat file: %s\n";
+      goto print_error;
+    }
+
+  /* Test the size.  If it does not match what we expect from the size
+     values in the map MAP we don't use it and warn the user.  */
+  if (st.st_size == 0)
+    {
+      /* We have to create the file.  */
+      char buf[GLRO(dl_pagesize)];
+
+      memset (buf, '\0', GLRO(dl_pagesize));
+
+      if (__lseek (fd, expected_size & ~(GLRO(dl_pagesize) - 1), SEEK_SET) == -1)
+	{
+	cannot_create:
+	  errstr = "%s: cannot create file: %s\n";
+	  goto print_error;
+	}
+
+      if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
+						      & (GLRO(dl_pagesize)
+							 - 1))))
+	  < 0)
+	goto cannot_create;
+    }
+  else if (st.st_size != expected_size)
+    {
+      __close (fd);
+    wrong_format:
+
+      if (addr != NULL)
+	__munmap ((void *) addr, expected_size);
+
+      _dl_error_printf ("%s: file is no correct profile data file for `%s'\n",
+			filename, GLRO(dl_profile));
+      return;
+    }
+
+  addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
+				     MAP_SHARED|MAP_FILE, fd, 0);
+  if (addr == (struct gmon_hdr *) MAP_FAILED)
+    {
+      errstr = "%s: cannot map file: %s\n";
+      goto print_error;
+    }
+
+  /* We don't need the file descriptor anymore.  */
+  __close (fd);
+
+  /* Pointer to data after the header.  */
+  hist = (char *) (addr + 1);
+  kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t)
+			 + sizeof (struct gmon_hist_hdr));
+
+  /* Compute pointer to array of the arc information.  */
+  narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t));
+  data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t));
+
+  if (st.st_size == 0)
+    {
+      /* Create the signature.  */
+      memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
+
+      *(uint32_t *) hist = GMON_TAG_TIME_HIST;
+      memcpy (hist + sizeof (uint32_t), &hist_hdr,
+	      sizeof (struct gmon_hist_hdr));
+
+      narcsp[-1] = GMON_TAG_CG_ARC;
+    }
+  else
+    {
+      /* Test the signature in the file.  */
+      if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
+	  || *(uint32_t *) hist != GMON_TAG_TIME_HIST
+	  || memcmp (hist + sizeof (uint32_t), &hist_hdr,
+		     sizeof (struct gmon_hist_hdr)) != 0
+	  || narcsp[-1] != GMON_TAG_CG_ARC)
+	goto wrong_format;
+    }
+
+  /* Allocate memory for the froms data and the pointer to the tos records.  */
+  tos = (uint16_t *) calloc (tossize + fromssize, 1);
+  if (tos == NULL)
+    {
+      __munmap ((void *) addr, expected_size);
+      _dl_fatal_printf ("Out of memory while initializing profiler\n");
+      /* NOTREACHED */
+    }
+
+  froms = (struct here_fromstruct *) ((char *) tos + tossize);
+  fromidx = 0;
+
+  /* Now we have to process all the arc count entries.  BTW: it is
+     not critical whether the *NARCSP value changes meanwhile.  Before
+     we enter a new entry in to toset we will check that everything is
+     available in TOS.  This happens in _dl_mcount.
+
+     Loading the entries in reverse order should help to get the most
+     frequently used entries at the front of the list.  */
+  for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; )
+    {
+      size_t to_index;
+      size_t newfromidx;
+      --idx;
+      to_index = (data[idx].self_pc / (HASHFRACTION * sizeof (*tos)));
+      newfromidx = fromidx++;
+      froms[newfromidx].here = &data[idx];
+      froms[newfromidx].link = tos[to_index];
+      tos[to_index] = newfromidx;
+    }
+
+  /* Setup counting data.  */
+  if (kcountsize < highpc - lowpc)
+    {
+#if 0
+      s_scale = ((double) kcountsize / (highpc - lowpc)) * SCALE_1_TO_1;
+#else
+      size_t range = highpc - lowpc;
+      size_t quot = range / kcountsize;
+
+      if (quot >= SCALE_1_TO_1)
+	s_scale = 1;
+      else if (quot >= SCALE_1_TO_1 / 256)
+	s_scale = SCALE_1_TO_1 / quot;
+      else if (range > ULONG_MAX / 256)
+	s_scale = (SCALE_1_TO_1 * 256) / (range / (kcountsize / 256));
+      else
+	s_scale = (SCALE_1_TO_1 * 256) / ((range * 256) / kcountsize);
+#endif
+    }
+  else
+    s_scale = SCALE_1_TO_1;
+
+  /* Start the profiler.  */
+  __profil ((void *) kcount, kcountsize, lowpc, s_scale);
+
+  /* Turn on profiling.  */
+  running = 1;
+}
+
+
+void
+_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
+{
+  volatile uint16_t *topcindex;
+  size_t i, fromindex;
+  struct here_fromstruct *fromp;
+
+  if (! running)
+    return;
+
+  /* Compute relative addresses.  The shared object can be loaded at
+     any address.  The value of frompc could be anything.  We cannot
+     restrict it in any way, just set to a fixed value (0) in case it
+     is outside the allowed range.  These calls show up as calls from
+     <external> in the gprof output.  */
+  frompc -= lowpc;
+  if (frompc >= textsize)
+    frompc = 0;
+  selfpc -= lowpc;
+  if (selfpc >= textsize)
+    goto done;
+
+  /* Getting here we now have to find out whether the location was
+     already used.  If yes we are lucky and only have to increment a
+     counter (this also has to be atomic).  If the entry is new things
+     are getting complicated...  */
+
+  /* Avoid integer divide if possible.  */
+  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
+    i = selfpc >> log_hashfraction;
+  else
+    i = selfpc / (HASHFRACTION * sizeof (*tos));
+
+  topcindex = &tos[i];
+  fromindex = *topcindex;
+
+  if (fromindex == 0)
+    goto check_new_or_add;
+
+  fromp = &froms[fromindex];
+
+  /* We have to look through the chain of arcs whether there is already
+     an entry for our arc.  */
+  while (fromp->here->from_pc != frompc)
+    {
+      if (fromp->link != 0)
+	do
+	  fromp = &froms[fromp->link];
+	while (fromp->link != 0 && fromp->here->from_pc != frompc);
+
+      if (fromp->here->from_pc != frompc)
+	{
+	  topcindex = &fromp->link;
+
+	check_new_or_add:
+	  /* Our entry is not among the entries we read so far from the
+	     data file.  Now see whether we have to update the list.  */
+	  while (narcs != *narcsp && narcs < fromlimit)
+	    {
+	      size_t to_index;
+	      size_t newfromidx;
+	      to_index = (data[narcs].self_pc
+			  / (HASHFRACTION * sizeof (*tos)));
+	      newfromidx = catomic_exchange_and_add (&fromidx, 1) + 1;
+	      froms[newfromidx].here = &data[narcs];
+	      froms[newfromidx].link = tos[to_index];
+	      tos[to_index] = newfromidx;
+	      catomic_increment (&narcs);
+	    }
+
+	  /* If we still have no entry stop searching and insert.  */
+	  if (*topcindex == 0)
+	    {
+	      uint_fast32_t newarc = catomic_exchange_and_add (narcsp, 1);
+
+	      /* In rare cases it could happen that all entries in FROMS are
+		 occupied.  So we cannot count this anymore.  */
+	      if (newarc >= fromlimit)
+		goto done;
+
+	      *topcindex = catomic_exchange_and_add (&fromidx, 1) + 1;
+	      fromp = &froms[*topcindex];
+
+	      fromp->here = &data[newarc];
+	      data[newarc].from_pc = frompc;
+	      data[newarc].self_pc = selfpc;
+	      data[newarc].count = 0;
+	      fromp->link = 0;
+	      catomic_increment (&narcs);
+
+	      break;
+	    }
+
+	  fromp = &froms[*topcindex];
+	}
+      else
+	/* Found in.  */
+	break;
+    }
+
+  /* Increment the counter.  */
+  catomic_increment (&fromp->here->count);
+
+ done:
+  ;
+}
+rtld_hidden_def (_dl_mcount)
diff --git a/REORG.TODO/elf/dl-profstub.c b/REORG.TODO/elf/dl-profstub.c
new file mode 100644
index 0000000000..0915e29093
--- /dev/null
+++ b/REORG.TODO/elf/dl-profstub.c
@@ -0,0 +1,41 @@
+/* Helper definitions for profiling of shared libraries.
+   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <elf.h>
+#include <ldsodefs.h>
+
+/* This is the map for the shared object we profile.  It is defined here
+   only because we test for this value being NULL or not.  */
+
+
+void
+_dl_mcount_wrapper (void *selfpc)
+{
+  GLRO(dl_mcount) ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
+}
+
+
+void
+_dl_mcount_wrapper_check (void *selfpc)
+{
+  if (GL(dl_profile_map) != NULL)
+    GLRO(dl_mcount) ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
+}
+libc_hidden_def (_dl_mcount_wrapper_check)
diff --git a/REORG.TODO/elf/dl-reloc.c b/REORG.TODO/elf/dl-reloc.c
new file mode 100644
index 0000000000..b3c3a9bbf9
--- /dev/null
+++ b/REORG.TODO/elf/dl-reloc.c
@@ -0,0 +1,363 @@
+/* Relocate a shared object and resolve its references to other loaded objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <_itoa.h>
+#include <libc-pointer-arith.h>
+#include "dynamic-link.h"
+
+/* Statistics function.  */
+#ifdef SHARED
+# define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
+#else
+# define bump_num_cache_relocations() ((void) 0)
+#endif
+
+
+/* We are trying to perform a static TLS relocation in MAP, but it was
+   dynamically loaded.  This can only work if there is enough surplus in
+   the static TLS area already allocated for each running thread.  If this
+   object's TLS segment is too big to fit, we fail.  If it fits,
+   we set MAP->l_tls_offset and return.
+   This function intentionally does not return any value but signals error
+   directly, as static TLS should be rare and code handling it should
+   not be inlined as much as possible.  */
+int
+internal_function
+_dl_try_allocate_static_tls (struct link_map *map)
+{
+  /* If we've already used the variable with dynamic access, or if the
+     alignment requirements are too high, fail.  */
+  if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
+      || map->l_tls_align > GL(dl_tls_static_align))
+    {
+    fail:
+      return -1;
+    }
+
+#if TLS_TCB_AT_TP
+  size_t freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used);
+  if (freebytes < TLS_TCB_SIZE)
+    goto fail;
+  freebytes -= TLS_TCB_SIZE;
+
+  size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
+  if (freebytes < blsize)
+    goto fail;
+
+  size_t n = (freebytes - blsize) / map->l_tls_align;
+
+  size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
+					    - map->l_tls_firstbyte_offset);
+
+  map->l_tls_offset = GL(dl_tls_static_used) = offset;
+#elif TLS_DTV_AT_TP
+  /* dl_tls_static_used includes the TCB at the beginning.  */
+  size_t offset = (ALIGN_UP(GL(dl_tls_static_used)
+			    - map->l_tls_firstbyte_offset,
+			    map->l_tls_align)
+		   + map->l_tls_firstbyte_offset);
+  size_t used = offset + map->l_tls_blocksize;
+
+  if (used > GL(dl_tls_static_size))
+    goto fail;
+
+  map->l_tls_offset = offset;
+  map->l_tls_firstbyte_offset = GL(dl_tls_static_used);
+  GL(dl_tls_static_used) = used;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+  /* If the object is not yet relocated we cannot initialize the
+     static TLS region.  Delay it.  */
+  if (map->l_real->l_relocated)
+    {
+#ifdef SHARED
+      if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
+			    0))
+	/* Update the slot information data for at least the generation of
+	   the DSO we are allocating data for.  */
+	(void) _dl_update_slotinfo (map->l_tls_modid);
+#endif
+
+      GL(dl_init_static_tls) (map);
+    }
+  else
+    map->l_need_tls_init = 1;
+
+  return 0;
+}
+
+void
+internal_function __attribute_noinline__
+_dl_allocate_static_tls (struct link_map *map)
+{
+  if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
+      || _dl_try_allocate_static_tls (map))
+    {
+      _dl_signal_error (0, map->l_name, NULL, N_("\
+cannot allocate memory in static TLS block"));
+    }
+}
+
+/* Initialize static TLS area and DTV for current (only) thread.
+   libpthread implementations should provide their own hook
+   to handle all threads.  */
+void
+_dl_nothread_init_static_tls (struct link_map *map)
+{
+#if TLS_TCB_AT_TP
+  void *dest = (char *) THREAD_SELF - map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+  void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+  /* Initialize the memory.  */
+  memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+}
+
+
+void
+_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
+		     int reloc_mode, int consider_profiling)
+{
+  struct textrels
+  {
+    caddr_t start;
+    size_t len;
+    int prot;
+    struct textrels *next;
+  } *textrels = NULL;
+  /* Initialize it to make the compiler happy.  */
+  const char *errstring = NULL;
+  int lazy = reloc_mode & RTLD_LAZY;
+  int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
+
+#ifdef SHARED
+  /* If we are auditing, install the same handlers we need for profiling.  */
+  if ((reloc_mode & __RTLD_AUDIT) == 0)
+    consider_profiling |= GLRO(dl_audit) != NULL;
+#elif defined PROF
+  /* Never use dynamic linker profiling for gprof profiling code.  */
+# define consider_profiling 0
+#endif
+
+  if (l->l_relocated)
+    return;
+
+  /* If DT_BIND_NOW is set relocate all references in this object.  We
+     do not do this if we are profiling, of course.  */
+  // XXX Correct for auditing?
+  if (!consider_profiling
+      && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
+    lazy = 0;
+
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
+    _dl_debug_printf ("\nrelocation processing: %s%s\n",
+		      DSO_FILENAME (l->l_name), lazy ? " (lazy)" : "");
+
+  /* DT_TEXTREL is now in level 2 and might phase out at some time.
+     But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
+     testing easier and therefore it will be available at all time.  */
+  if (__glibc_unlikely (l->l_info[DT_TEXTREL] != NULL))
+    {
+      /* Bletch.  We must make read-only segments writable
+	 long enough to relocate them.  */
+      const ElfW(Phdr) *ph;
+      for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
+	if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
+	  {
+	    struct textrels *newp;
+
+	    newp = (struct textrels *) alloca (sizeof (*newp));
+	    newp->len = ALIGN_UP (ph->p_vaddr + ph->p_memsz, GLRO(dl_pagesize))
+			- ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
+	    newp->start = PTR_ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize))
+			  + (caddr_t) l->l_addr;
+
+	    if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
+	      {
+		errstring = N_("cannot make segment writable for relocation");
+	      call_error:
+		_dl_signal_error (errno, l->l_name, NULL, errstring);
+	      }
+
+#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
+	    newp->prot = (PF_TO_PROT
+			  >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
+#else
+	    newp->prot = 0;
+	    if (ph->p_flags & PF_R)
+	      newp->prot |= PROT_READ;
+	    if (ph->p_flags & PF_W)
+	      newp->prot |= PROT_WRITE;
+	    if (ph->p_flags & PF_X)
+	      newp->prot |= PROT_EXEC;
+#endif
+	    newp->next = textrels;
+	    textrels = newp;
+	  }
+    }
+
+  {
+    /* Do the actual relocation of the object's GOT and other data.  */
+
+    /* String table object symbols.  */
+    const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+
+    /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
+#define RESOLVE_MAP(ref, version, r_type) \
+    ((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \
+      && __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref)))	      \
+     ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0)		      \
+	 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class)  \
+	? (bump_num_cache_relocations (),				      \
+	   (*ref) = l->l_lookup_cache.ret,				      \
+	   l->l_lookup_cache.value)					      \
+	: ({ lookup_t _lr;						      \
+	     int _tc = elf_machine_type_class (r_type);			      \
+	     l->l_lookup_cache.type_class = _tc;			      \
+	     l->l_lookup_cache.sym = (*ref);				      \
+	     const struct r_found_version *v = NULL;			      \
+	     if ((version) != NULL && (version)->hash != 0)		      \
+	       v = (version);						      \
+	     _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref),   \
+					scope, v, _tc,			      \
+					DL_LOOKUP_ADD_DEPENDENCY, NULL);      \
+	     l->l_lookup_cache.ret = (*ref);				      \
+	     l->l_lookup_cache.value = _lr; }))				      \
+     : l)
+
+#include "dynamic-link.h"
+
+    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
+
+#ifndef PROF
+    if (__glibc_unlikely (consider_profiling)
+	&& l->l_info[DT_PLTRELSZ] != NULL)
+      {
+	/* Allocate the array which will contain the already found
+	   relocations.  If the shared object lacks a PLT (for example
+	   if it only contains lead function) the l_info[DT_PLTRELSZ]
+	   will be NULL.  */
+	size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA
+			   ? sizeof (ElfW(Rela))
+			   : sizeof (ElfW(Rel));
+	size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel;
+	l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount);
+
+	if (l->l_reloc_result == NULL)
+	  {
+	    errstring = N_("\
+%s: out of memory to store relocation results for %s\n");
+	    _dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name);
+	  }
+      }
+#endif
+  }
+
+  /* Mark the object so we know this work has been done.  */
+  l->l_relocated = 1;
+
+  /* Undo the segment protection changes.  */
+  while (__builtin_expect (textrels != NULL, 0))
+    {
+      if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
+	{
+	  errstring = N_("cannot restore segment prot after reloc");
+	  goto call_error;
+	}
+
+#ifdef CLEAR_CACHE
+      CLEAR_CACHE (textrels->start, textrels->start + textrels->len);
+#endif
+
+      textrels = textrels->next;
+    }
+
+  /* In case we can protect the data now that the relocations are
+     done, do it.  */
+  if (l->l_relro_size != 0)
+    _dl_protect_relro (l);
+}
+
+
+void internal_function
+_dl_protect_relro (struct link_map *l)
+{
+  ElfW(Addr) start = ALIGN_DOWN((l->l_addr
+				 + l->l_relro_addr),
+				GLRO(dl_pagesize));
+  ElfW(Addr) end = ALIGN_DOWN((l->l_addr
+			       + l->l_relro_addr
+			       + l->l_relro_size),
+			      GLRO(dl_pagesize));
+  if (start != end
+      && __mprotect ((void *) start, end - start, PROT_READ) < 0)
+    {
+      static const char errstring[] = N_("\
+cannot apply additional memory protection after relocation");
+      _dl_signal_error (errno, l->l_name, NULL, errstring);
+    }
+}
+
+void
+internal_function __attribute_noinline__
+_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
+{
+#define DIGIT(b)	_itoa_lower_digits[(b) & 0xf];
+
+  /* XXX We cannot translate these messages.  */
+  static const char msg[2][32
+#if __ELF_NATIVE_CLASS == 64
+			   + 6
+#endif
+  ] = { "unexpected reloc type 0x",
+	"unexpected PLT reloc type 0x" };
+  char msgbuf[sizeof (msg[0])];
+  char *cp;
+
+  cp = __stpcpy (msgbuf, msg[plt]);
+#if __ELF_NATIVE_CLASS == 64
+  if (__builtin_expect(type > 0xff, 0))
+    {
+      *cp++ = DIGIT (type >> 28);
+      *cp++ = DIGIT (type >> 24);
+      *cp++ = DIGIT (type >> 20);
+      *cp++ = DIGIT (type >> 16);
+      *cp++ = DIGIT (type >> 12);
+      *cp++ = DIGIT (type >> 8);
+    }
+#endif
+  *cp++ = DIGIT (type >> 4);
+  *cp++ = DIGIT (type);
+  *cp = '\0';
+
+  _dl_signal_error (0, map->l_name, NULL, msgbuf);
+}
diff --git a/REORG.TODO/elf/dl-runtime.c b/REORG.TODO/elf/dl-runtime.c
new file mode 100644
index 0000000000..7d1d240403
--- /dev/null
+++ b/REORG.TODO/elf/dl-runtime.c
@@ -0,0 +1,480 @@
+/* On-demand PLT fixup for shared objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define IN_DL_RUNTIME 1		/* This can be tested in dl-machine.h.  */
+
+#include <alloca.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <ldsodefs.h>
+#include <sysdep-cancel.h>
+#include "dynamic-link.h"
+#include <tls.h>
+#include <dl-irel.h>
+
+
+#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
+    || ELF_MACHINE_NO_REL
+# define PLTREL  ElfW(Rela)
+#else
+# define PLTREL  ElfW(Rel)
+#endif
+
+/* The fixup functions might have need special attributes.  If none
+   are provided define the macro as empty.  */
+#ifndef ARCH_FIXUP_ATTRIBUTE
+# define ARCH_FIXUP_ATTRIBUTE
+#endif
+
+#ifndef reloc_offset
+# define reloc_offset reloc_arg
+# define reloc_index  reloc_arg / sizeof (PLTREL)
+#endif
+
+
+
+/* This function is called through a special trampoline from the PLT the
+   first time each PLT entry is called.  We must perform the relocation
+   specified in the PLT of the given shared object, and return the resolved
+   function address to the trampoline, which will restart the original call
+   to that address.  Future calls will bounce directly from the PLT to the
+   function.  */
+
+DL_FIXUP_VALUE_TYPE
+attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+_dl_fixup (
+# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+	   ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+# endif
+	   struct link_map *l, ElfW(Word) reloc_arg)
+{
+  const ElfW(Sym) *const symtab
+    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
+  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+
+  const PLTREL *const reloc
+    = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
+  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+  void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
+  lookup_t result;
+  DL_FIXUP_VALUE_TYPE value;
+
+  /* Sanity check that we're really looking at a PLT relocation.  */
+  assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
+
+   /* Look up the target symbol.  If the normal lookup rules are not
+      used don't look in the global scope.  */
+  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
+    {
+      const struct r_found_version *version = NULL;
+
+      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+	{
+	  const ElfW(Half) *vernum =
+	    (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
+	  ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
+	  version = &l->l_versions[ndx];
+	  if (version->hash == 0)
+	    version = NULL;
+	}
+
+      /* We need to keep the scope around so do some locking.  This is
+	 not necessary for objects which cannot be unloaded or when
+	 we are not using any threads (yet).  */
+      int flags = DL_LOOKUP_ADD_DEPENDENCY;
+      if (!RTLD_SINGLE_THREAD_P)
+	{
+	  THREAD_GSCOPE_SET_FLAG ();
+	  flags |= DL_LOOKUP_GSCOPE_LOCK;
+	}
+
+#ifdef RTLD_ENABLE_FOREIGN_CALL
+      RTLD_ENABLE_FOREIGN_CALL;
+#endif
+
+      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
+				    version, ELF_RTYPE_CLASS_PLT, flags, NULL);
+
+      /* We are done with the global scope.  */
+      if (!RTLD_SINGLE_THREAD_P)
+	THREAD_GSCOPE_RESET_FLAG ();
+
+#ifdef RTLD_FINALIZE_FOREIGN_CALL
+      RTLD_FINALIZE_FOREIGN_CALL;
+#endif
+
+      /* Currently result contains the base load address (or link map)
+	 of the object that defines sym.  Now add in the symbol
+	 offset.  */
+      value = DL_FIXUP_MAKE_VALUE (result,
+				   sym ? (LOOKUP_VALUE_ADDRESS (result)
+					  + sym->st_value) : 0);
+    }
+  else
+    {
+      /* We already found the symbol.  The module (and therefore its load
+	 address) is also known.  */
+      value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value);
+      result = l;
+    }
+
+  /* And now perhaps the relocation addend.  */
+  value = elf_machine_plt_value (l, reloc, value);
+
+  if (sym != NULL
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
+    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
+
+  /* Finally, fix up the plt itself.  */
+  if (__glibc_unlikely (GLRO(dl_bind_not)))
+    return value;
+
+  return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
+}
+
+#ifndef PROF
+DL_FIXUP_VALUE_TYPE
+__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+_dl_profile_fixup (
+#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+		   ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+#endif
+		   struct link_map *l, ElfW(Word) reloc_arg,
+		   ElfW(Addr) retaddr, void *regs, long int *framesizep)
+{
+  void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
+
+  if (l->l_reloc_result == NULL)
+    {
+      /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result
+	 is allocated.  We will get here if ELF_DYNAMIC_RELOCATE calls a
+	 resolver function to resolve an IRELATIVE relocation and that
+	 resolver calls a function that is not yet resolved (lazy).  For
+	 example, the resolver in x86-64 libm.so calls __get_cpu_features
+	 defined in libc.so.  Skip audit and resolve the external function
+	 in this case.  */
+      *framesizep = -1;
+      return _dl_fixup (
+# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+#  ifndef ELF_MACHINE_RUNTIME_FIXUP_PARAMS
+#   error Please define ELF_MACHINE_RUNTIME_FIXUP_PARAMS.
+#  endif
+			ELF_MACHINE_RUNTIME_FIXUP_PARAMS,
+# endif
+			l, reloc_arg);
+    }
+
+  /* This is the address in the array where we store the result of previous
+     relocations.  */
+  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
+  DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
+
+  DL_FIXUP_VALUE_TYPE value = *resultp;
+  if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
+    {
+      /* This is the first time we have to relocate this object.  */
+      const ElfW(Sym) *const symtab
+	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
+      const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
+
+      const PLTREL *const reloc
+	= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
+      const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+      const ElfW(Sym) *defsym = refsym;
+      lookup_t result;
+
+      /* Sanity check that we're really looking at a PLT relocation.  */
+      assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
+
+      /* Look up the target symbol.  If the symbol is marked STV_PROTECTED
+	 don't look in the global scope.  */
+      if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
+	{
+	  const struct r_found_version *version = NULL;
+
+	  if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+	    {
+	      const ElfW(Half) *vernum =
+		(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
+	      ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
+	      version = &l->l_versions[ndx];
+	      if (version->hash == 0)
+		version = NULL;
+	    }
+
+	  /* We need to keep the scope around so do some locking.  This is
+	     not necessary for objects which cannot be unloaded or when
+	     we are not using any threads (yet).  */
+	  int flags = DL_LOOKUP_ADD_DEPENDENCY;
+	  if (!RTLD_SINGLE_THREAD_P)
+	    {
+	      THREAD_GSCOPE_SET_FLAG ();
+	      flags |= DL_LOOKUP_GSCOPE_LOCK;
+	    }
+
+	  result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
+					&defsym, l->l_scope, version,
+					ELF_RTYPE_CLASS_PLT, flags, NULL);
+
+	  /* We are done with the global scope.  */
+	  if (!RTLD_SINGLE_THREAD_P)
+	    THREAD_GSCOPE_RESET_FLAG ();
+
+	  /* Currently result contains the base load address (or link map)
+	     of the object that defines sym.  Now add in the symbol
+	     offset.  */
+	  value = DL_FIXUP_MAKE_VALUE (result,
+				       defsym != NULL
+				       ? LOOKUP_VALUE_ADDRESS (result)
+					 + defsym->st_value : 0);
+
+	  if (defsym != NULL
+	      && __builtin_expect (ELFW(ST_TYPE) (defsym->st_info)
+				   == STT_GNU_IFUNC, 0))
+	    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
+	}
+      else
+	{
+	  /* We already found the symbol.  The module (and therefore its load
+	     address) is also known.  */
+	  value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value);
+
+	  if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info)
+				== STT_GNU_IFUNC, 0))
+	    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
+
+	  result = l;
+	}
+      /* And now perhaps the relocation addend.  */
+      value = elf_machine_plt_value (l, reloc, value);
+
+#ifdef SHARED
+      /* Auditing checkpoint: we have a new binding.  Provide the
+	 auditing libraries the possibility to change the value and
+	 tell us whether further auditing is wanted.  */
+      if (defsym != NULL && GLRO(dl_naudit) > 0)
+	{
+	  reloc_result->bound = result;
+	  /* Compute index of the symbol entry in the symbol table of
+	     the DSO with the definition.  */
+	  reloc_result->boundndx = (defsym
+				    - (ElfW(Sym) *) D_PTR (result,
+							   l_info[DT_SYMTAB]));
+
+	  /* Determine whether any of the two participating DSOs is
+	     interested in auditing.  */
+	  if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
+	    {
+	      unsigned int flags = 0;
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      /* Synthesize a symbol record where the st_value field is
+		 the result.  */
+	      ElfW(Sym) sym = *defsym;
+	      sym.st_value = DL_FIXUP_VALUE_ADDR (value);
+
+	      /* Keep track whether there is any interest in tracing
+		 the call in the lower two bits.  */
+	      assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
+	      assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
+	      reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
+
+	      const char *strtab2 = (const void *) D_PTR (result,
+							  l_info[DT_STRTAB]);
+
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  /* XXX Check whether both DSOs must request action or
+		     only one */
+		  if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
+		      && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
+		    {
+		      if (afct->symbind != NULL)
+			{
+			  uintptr_t new_value
+			    = afct->symbind (&sym, reloc_result->boundndx,
+					     &l->l_audit[cnt].cookie,
+					     &result->l_audit[cnt].cookie,
+					     &flags,
+					     strtab2 + defsym->st_name);
+			  if (new_value != (uintptr_t) sym.st_value)
+			    {
+			      flags |= LA_SYMB_ALTVALUE;
+			      sym.st_value = new_value;
+			    }
+			}
+
+		      /* Remember the results for every audit library and
+			 store a summary in the first two bits.  */
+		      reloc_result->enterexit
+			&= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
+		      reloc_result->enterexit
+			|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
+			    << ((cnt + 1) * 2));
+		    }
+		  else
+		    /* If the bind flags say this auditor is not interested,
+		       set the bits manually.  */
+		    reloc_result->enterexit
+		      |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
+			  << ((cnt + 1) * 2));
+
+		  afct = afct->next;
+		}
+
+	      reloc_result->flags = flags;
+	      value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+	    }
+	  else
+	    /* Set all bits since this symbol binding is not interesting.  */
+	    reloc_result->enterexit = (1u << DL_NNS) - 1;
+	}
+#endif
+
+      /* Store the result for later runs.  */
+      if (__glibc_likely (! GLRO(dl_bind_not)))
+	*resultp = value;
+    }
+
+  /* By default we do not call the pltexit function.  */
+  long int framesize = -1;
+
+#ifdef SHARED
+  /* Auditing checkpoint: report the PLT entering and allow the
+     auditors to change the value.  */
+  if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
+      /* Don't do anything if no auditor wants to intercept this call.  */
+      && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
+    {
+      ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+						l_info[DT_SYMTAB])
+			   + reloc_result->boundndx);
+
+      /* Set up the sym parameter.  */
+      ElfW(Sym) sym = *defsym;
+      sym.st_value = DL_FIXUP_VALUE_ADDR (value);
+
+      /* Get the symbol name.  */
+      const char *strtab = (const void *) D_PTR (reloc_result->bound,
+						 l_info[DT_STRTAB]);
+      const char *symname = strtab + sym.st_name;
+
+      /* Keep track of overwritten addresses.  */
+      unsigned int flags = reloc_result->flags;
+
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->ARCH_LA_PLTENTER != NULL
+	      && (reloc_result->enterexit
+		  & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
+	    {
+	      long int new_framesize = -1;
+	      uintptr_t new_value
+		= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
+					  &l->l_audit[cnt].cookie,
+					  &reloc_result->bound->l_audit[cnt].cookie,
+					  regs, &flags, symname,
+					  &new_framesize);
+	      if (new_value != (uintptr_t) sym.st_value)
+		{
+		  flags |= LA_SYMB_ALTVALUE;
+		  sym.st_value = new_value;
+		}
+
+	      /* Remember the results for every audit library and
+		 store a summary in the first two bits.  */
+	      reloc_result->enterexit
+		|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
+		    << (2 * (cnt + 1)));
+
+	      if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
+					      << (2 * (cnt + 1))))
+		  == 0 && new_framesize != -1 && framesize != -2)
+		{
+		  /* If this is the first call providing information,
+		     use it.  */
+		  if (framesize == -1)
+		    framesize = new_framesize;
+		  /* If two pltenter calls provide conflicting information,
+		     use the larger value.  */
+		  else if (new_framesize != framesize)
+		    framesize = MAX (new_framesize, framesize);
+		}
+	    }
+
+	  afct = afct->next;
+	}
+
+      value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+    }
+#endif
+
+  /* Store the frame size information.  */
+  *framesizep = framesize;
+
+  (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
+
+  return value;
+}
+
+#endif /* PROF */
+
+
+#include <stdio.h>
+void
+ARCH_FIXUP_ATTRIBUTE
+_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
+		  const void *inregs, void *outregs)
+{
+#ifdef SHARED
+  /* This is the address in the array where we store the result of previous
+     relocations.  */
+  // XXX Maybe the bound information must be stored on the stack since
+  // XXX with bind_not a new value could have been stored in the meantime.
+  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
+  ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+					    l_info[DT_SYMTAB])
+		       + reloc_result->boundndx);
+
+  /* Set up the sym parameter.  */
+  ElfW(Sym) sym = *defsym;
+  sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
+
+  /* Get the symbol name.  */
+  const char *strtab = (const void *) D_PTR (reloc_result->bound,
+					     l_info[DT_STRTAB]);
+  const char *symname = strtab + sym.st_name;
+
+  struct audit_ifaces *afct = GLRO(dl_audit);
+  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+    {
+      if (afct->ARCH_LA_PLTEXIT != NULL
+	  && (reloc_result->enterexit
+	      & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
+	{
+	  afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
+				 &l->l_audit[cnt].cookie,
+				 &reloc_result->bound->l_audit[cnt].cookie,
+				 inregs, outregs, symname);
+	}
+
+      afct = afct->next;
+    }
+#endif
+}
diff --git a/REORG.TODO/elf/dl-sbrk.c b/REORG.TODO/elf/dl-sbrk.c
new file mode 100644
index 0000000000..4713a92694
--- /dev/null
+++ b/REORG.TODO/elf/dl-sbrk.c
@@ -0,0 +1,5 @@
+/* We can use the normal code but we also know the __curbrk is not exported
+   from ld.so.  */
+extern void *__curbrk attribute_hidden;
+
+#include <sbrk.c>
diff --git a/REORG.TODO/elf/dl-scope.c b/REORG.TODO/elf/dl-scope.c
new file mode 100644
index 0000000000..bb924afa8f
--- /dev/null
+++ b/REORG.TODO/elf/dl-scope.c
@@ -0,0 +1,57 @@
+/* Memory handling for the scope data structures.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <ldsodefs.h>
+#include <sysdep-cancel.h>
+
+
+int
+_dl_scope_free (void *old)
+{
+  struct dl_scope_free_list *fsl;
+#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0]))
+
+  if (RTLD_SINGLE_THREAD_P)
+    free (old);
+  else if ((fsl = GL(dl_scope_free_list)) == NULL)
+    {
+      GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl));
+      if (fsl == NULL)
+	{
+	  THREAD_GSCOPE_WAIT ();
+	  free (old);
+	  return 1;
+	}
+      else
+	{
+	  fsl->list[0] = old;
+	  fsl->count = 1;
+	}
+    }
+  else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE)
+    fsl->list[fsl->count++] = old;
+  else
+    {
+      THREAD_GSCOPE_WAIT ();
+      while (fsl->count > 0)
+	free (fsl->list[--fsl->count]);
+      return 1;
+    }
+  return 0;
+}
diff --git a/REORG.TODO/elf/dl-support.c b/REORG.TODO/elf/dl-support.c
new file mode 100644
index 0000000000..c22be854f4
--- /dev/null
+++ b/REORG.TODO/elf/dl-support.c
@@ -0,0 +1,389 @@
+/* Support for dynamic linking code in static libc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file defines some things that for the dynamic linker are defined in
+   rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking.  */
+
+#include <errno.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <stdint.h>
+#include <ldsodefs.h>
+#include <dl-machine.h>
+#include <libc-lock.h>
+#include <dl-cache.h>
+#include <dl-librecon.h>
+#include <dl-procinfo.h>
+#include <unsecvars.h>
+#include <hp-timing.h>
+#include <stackinfo.h>
+
+extern char *__progname;
+char **_dl_argv = &__progname;	/* This is checked for some error messages.  */
+
+/* Name of the architecture.  */
+const char *_dl_platform;
+size_t _dl_platformlen;
+
+int _dl_debug_mask;
+int _dl_lazy;
+ElfW(Addr) _dl_use_load_bias = -2;
+int _dl_dynamic_weak;
+
+/* If nonzero print warnings about problematic situations.  */
+int _dl_verbose;
+
+/* We never do profiling.  */
+const char *_dl_profile;
+const char *_dl_profile_output;
+
+/* Names of shared object for which the RUNPATHs and RPATHs should be
+   ignored.  */
+const char *_dl_inhibit_rpath;
+
+/* The map for the object we will profile.  */
+struct link_map *_dl_profile_map;
+
+/* This is the address of the last stack address ever used.  */
+void *__libc_stack_end;
+
+/* Path where the binary is found.  */
+const char *_dl_origin_path;
+
+/* Nonzero if runtime lookup should not update the .got/.plt.  */
+int _dl_bind_not;
+
+/* A dummy link map for the executable, used by dlopen to access the global
+   scope.  We don't export any symbols ourselves, so this can be minimal.  */
+static struct link_map _dl_main_map =
+  {
+    .l_name = (char *) "",
+    .l_real = &_dl_main_map,
+    .l_ns = LM_ID_BASE,
+    .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
+    .l_searchlist =
+      {
+	.r_list = &(struct link_map *) { &_dl_main_map },
+	.r_nlist = 1,
+      },
+    .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } },
+    .l_type = lt_executable,
+    .l_scope_mem = { &_dl_main_map.l_searchlist },
+    .l_scope_max = (sizeof (_dl_main_map.l_scope_mem)
+		    / sizeof (_dl_main_map.l_scope_mem[0])),
+    .l_scope = _dl_main_map.l_scope_mem,
+    .l_local_scope = { &_dl_main_map.l_searchlist },
+    .l_used = 1,
+    .l_tls_offset = NO_TLS_OFFSET,
+    .l_serial = 1,
+  };
+
+/* Namespace information.  */
+struct link_namespaces _dl_ns[DL_NNS] =
+  {
+    [LM_ID_BASE] =
+      {
+	._ns_loaded = &_dl_main_map,
+	._ns_nloaded = 1,
+	._ns_main_searchlist = &_dl_main_map.l_searchlist,
+      }
+  };
+size_t _dl_nns = 1;
+
+/* Incremented whenever something may have been added to dl_loaded. */
+unsigned long long _dl_load_adds = 1;
+
+/* Fake scope of the main application.  */
+struct r_scope_elem _dl_initial_searchlist =
+  {
+    .r_list = &(struct link_map *) { &_dl_main_map },
+    .r_nlist = 1,
+  };
+
+#ifndef HAVE_INLINED_SYSCALLS
+/* Nonzero during startup.  */
+int _dl_starting_up = 1;
+#endif
+
+/* Random data provided by the kernel.  */
+void *_dl_random;
+
+/* Get architecture specific initializer.  */
+#include <dl-procinfo.c>
+
+/* Initial value of the CPU clock.  */
+#ifndef HP_TIMING_NONAVAIL
+hp_timing_t _dl_cpuclock_offset;
+#endif
+
+void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
+
+size_t _dl_pagesize = EXEC_PAGESIZE;
+
+int _dl_inhibit_cache;
+
+unsigned int _dl_osversion;
+
+/* All known directories in sorted order.  */
+struct r_search_path_elem *_dl_all_dirs;
+
+/* All directories after startup.  */
+struct r_search_path_elem *_dl_init_all_dirs;
+
+/* The object to be initialized first.  */
+struct link_map *_dl_initfirst;
+
+/* Descriptor to write debug messages to.  */
+int _dl_debug_fd = STDERR_FILENO;
+
+int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID;
+
+ElfW(auxv_t) *_dl_auxv;
+const ElfW(Phdr) *_dl_phdr;
+size_t _dl_phnum;
+uint64_t _dl_hwcap __attribute__ ((nocommon));
+uint64_t _dl_hwcap2 __attribute__ ((nocommon));
+
+/* The value of the FPU control word the kernel will preset in hardware.  */
+fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
+
+#if !HAVE_TUNABLES
+/* This is not initialized to HWCAP_IMPORTANT, matching the definition
+   of _dl_important_hwcaps, below, where no hwcap strings are ever
+   used.  This mask is still used to mediate the lookups in the cache
+   file.  Since there is no way to set this nonzero (we don't grok the
+   LD_HWCAP_MASK environment variable here), there is no real point in
+   setting _dl_hwcap nonzero below, but we do anyway.  */
+uint64_t _dl_hwcap_mask __attribute__ ((nocommon));
+#endif
+
+/* Prevailing state of the stack.  Generally this includes PF_X, indicating it's
+ * executable but this isn't true for all platforms.  */
+ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS;
+
+/* If loading a shared object requires that we make the stack executable
+   when it was not, we do it by calling this function.
+   It returns an errno code or zero on success.  */
+int (*_dl_make_stack_executable_hook) (void **) internal_function
+  = _dl_make_stack_executable;
+
+
+/* Function in libpthread to wait for termination of lookups.  */
+void (*_dl_wait_lookup_done) (void);
+
+struct dl_scope_free_list *_dl_scope_free_list;
+
+#ifdef NEED_DL_SYSINFO
+/* Needed for improved syscall handling on at least x86/Linux.  */
+uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT;
+#endif
+#ifdef NEED_DL_SYSINFO_DSO
+/* Address of the ELF headers in the vsyscall page.  */
+const ElfW(Ehdr) *_dl_sysinfo_dso;
+
+struct link_map *_dl_sysinfo_map;
+
+# include "get-dynamic-info.h"
+#endif
+#include "setup-vdso.h"
+
+/* During the program run we must not modify the global data of
+   loaded shared object simultanously in two threads.  Therefore we
+   protect `_dl_open' and `_dl_close' in dl-close.c.
+
+   This must be a recursive lock since the initializer function of
+   the loaded object might as well require a call to this function.
+   At this time it is not anymore a problem to modify the tables.  */
+__rtld_lock_define_initialized_recursive (, _dl_load_lock)
+/* This lock is used to keep __dl_iterate_phdr from inspecting the
+   list of loaded objects while an object is added to or removed from
+   that list.  */
+__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
+
+
+#ifdef HAVE_AUX_VECTOR
+int _dl_clktck;
+
+void
+internal_function
+_dl_aux_init (ElfW(auxv_t) *av)
+{
+  int seen = 0;
+  uid_t uid = 0;
+  gid_t gid = 0;
+
+  _dl_auxv = av;
+  for (; av->a_type != AT_NULL; ++av)
+    switch (av->a_type)
+      {
+      case AT_PAGESZ:
+	if (av->a_un.a_val != 0)
+	  GLRO(dl_pagesize) = av->a_un.a_val;
+	break;
+      case AT_CLKTCK:
+	GLRO(dl_clktck) = av->a_un.a_val;
+	break;
+      case AT_PHDR:
+	GL(dl_phdr) = (const void *) av->a_un.a_val;
+	break;
+      case AT_PHNUM:
+	GL(dl_phnum) = av->a_un.a_val;
+	break;
+      case AT_PLATFORM:
+	GLRO(dl_platform) = (void *) av->a_un.a_val;
+	break;
+      case AT_HWCAP:
+	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_HWCAP2:
+	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_FPUCW:
+	GLRO(dl_fpu_control) = av->a_un.a_val;
+	break;
+#ifdef NEED_DL_SYSINFO
+      case AT_SYSINFO:
+	GL(dl_sysinfo) = av->a_un.a_val;
+	break;
+#endif
+#ifdef NEED_DL_SYSINFO_DSO
+      case AT_SYSINFO_EHDR:
+	GL(dl_sysinfo_dso) = (void *) av->a_un.a_val;
+	break;
+#endif
+      case AT_UID:
+	uid ^= av->a_un.a_val;
+	seen |= 1;
+	break;
+      case AT_EUID:
+	uid ^= av->a_un.a_val;
+	seen |= 2;
+	break;
+      case AT_GID:
+	gid ^= av->a_un.a_val;
+	seen |= 4;
+	break;
+      case AT_EGID:
+	gid ^= av->a_un.a_val;
+	seen |= 8;
+	break;
+      case AT_SECURE:
+	seen = -1;
+	__libc_enable_secure = av->a_un.a_val;
+	__libc_enable_secure_decided = 1;
+	break;
+      case AT_RANDOM:
+	_dl_random = (void *) av->a_un.a_val;
+	break;
+# ifdef DL_PLATFORM_AUXV
+      DL_PLATFORM_AUXV
+# endif
+      }
+  if (seen == 0xf)
+    {
+      __libc_enable_secure = uid != 0 || gid != 0;
+      __libc_enable_secure_decided = 1;
+    }
+}
+#endif
+
+
+void
+internal_function
+_dl_non_dynamic_init (void)
+{
+  _dl_main_map.l_origin = _dl_get_origin ();
+  _dl_main_map.l_phdr = GL(dl_phdr);
+  _dl_main_map.l_phnum = GL(dl_phnum);
+
+  if (HP_SMALL_TIMING_AVAIL)
+    HP_TIMING_NOW (_dl_cpuclock_offset);
+
+  _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
+
+  /* Set up the data structures for the system-supplied DSO early,
+     so they can influence _dl_init_paths.  */
+  setup_vdso (NULL, NULL);
+
+  /* Initialize the data structures for the search paths for shared
+     objects.  */
+  _dl_init_paths (getenv ("LD_LIBRARY_PATH"));
+
+  /* Remember the last search directory added at startup.  */
+  _dl_init_all_dirs = GL(dl_all_dirs);
+
+  _dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0';
+
+  _dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0';
+
+  _dl_dynamic_weak = *(getenv ("LD_DYNAMIC_WEAK") ?: "") == '\0';
+
+  _dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
+  if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
+    _dl_profile_output
+      = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];
+
+  if (__libc_enable_secure)
+    {
+      static const char unsecure_envvars[] =
+	UNSECURE_ENVVARS
+#ifdef EXTRA_UNSECURE_ENVVARS
+	EXTRA_UNSECURE_ENVVARS
+#endif
+	;
+      const char *cp = unsecure_envvars;
+
+      while (cp < unsecure_envvars + sizeof (unsecure_envvars))
+	{
+	  __unsetenv (cp);
+	  cp = (const char *) __rawmemchr (cp, '\0') + 1;
+	}
+
+#if !HAVE_TUNABLES
+      if (__access ("/etc/suid-debug", F_OK) != 0)
+	__unsetenv ("MALLOC_CHECK_");
+#endif
+    }
+
+#ifdef DL_PLATFORM_INIT
+  DL_PLATFORM_INIT;
+#endif
+
+#ifdef DL_OSVERSION_INIT
+  DL_OSVERSION_INIT;
+#endif
+
+  /* Now determine the length of the platform string.  */
+  if (_dl_platform != NULL)
+    _dl_platformlen = strlen (_dl_platform);
+
+  /* Scan for a program header telling us the stack is nonexecutable.  */
+  if (_dl_phdr != NULL)
+    for (uint_fast16_t i = 0; i < _dl_phnum; ++i)
+      if (_dl_phdr[i].p_type == PT_GNU_STACK)
+	{
+	  _dl_stack_flags = _dl_phdr[i].p_flags;
+	  break;
+	}
+}
+
+#ifdef DL_SYSINFO_IMPLEMENTATION
+DL_SYSINFO_IMPLEMENTATION
+#endif
diff --git a/REORG.TODO/elf/dl-sym.c b/REORG.TODO/elf/dl-sym.c
new file mode 100644
index 0000000000..7cd6e97643
--- /dev/null
+++ b/REORG.TODO/elf/dl-sym.c
@@ -0,0 +1,274 @@
+/* Look up a symbol in a shared object loaded by `dlopen'.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <libintl.h>
+
+#include <dlfcn.h>
+#include <ldsodefs.h>
+#include <dl-hash.h>
+#include <sysdep-cancel.h>
+#include <dl-tls.h>
+#include <dl-irel.h>
+
+
+#ifdef SHARED
+/* Systems which do not have tls_index also probably have to define
+   DONT_USE_TLS_INDEX.  */
+
+# ifndef __TLS_GET_ADDR
+#  define __TLS_GET_ADDR __tls_get_addr
+# endif
+
+/* Return the symbol address given the map of the module it is in and
+   the symbol record.  This is used in dl-sym.c.  */
+static void *
+internal_function
+_dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref)
+{
+# ifndef DONT_USE_TLS_INDEX
+  tls_index tmp =
+    {
+      .ti_module = map->l_tls_modid,
+      .ti_offset = ref->st_value
+    };
+
+  return __TLS_GET_ADDR (&tmp);
+# else
+  return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value);
+# endif
+}
+#endif
+
+
+struct call_dl_lookup_args
+{
+  /* Arguments to do_dlsym.  */
+  struct link_map *map;
+  const char *name;
+  struct r_found_version *vers;
+  int flags;
+
+  /* Return values of do_dlsym.  */
+  lookup_t loadbase;
+  const ElfW(Sym) **refp;
+};
+
+static void
+call_dl_lookup (void *ptr)
+{
+  struct call_dl_lookup_args *args = (struct call_dl_lookup_args *) ptr;
+  args->map = GLRO(dl_lookup_symbol_x) (args->name, args->map, args->refp,
+					args->map->l_scope, args->vers, 0,
+					args->flags, NULL);
+}
+
+
+static void *
+internal_function
+do_sym (void *handle, const char *name, void *who,
+	struct r_found_version *vers, int flags)
+{
+  const ElfW(Sym) *ref = NULL;
+  lookup_t result;
+  ElfW(Addr) caller = (ElfW(Addr)) who;
+
+  struct link_map *l = _dl_find_dso_for_object (caller);
+  /* If the address is not recognized the call comes from the main
+     program (we hope).  */
+  struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+  if (handle == RTLD_DEFAULT)
+    {
+      /* Search the global scope.  We have the simple case where
+	 we look up in the scope of an object which was part of
+	 the initial binary.  And then the more complex part
+	 where the object is dynamically loaded and the scope
+	 array can change.  */
+      if (RTLD_SINGLE_THREAD_P)
+	result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
+					   match->l_scope, vers, 0,
+					   flags | DL_LOOKUP_ADD_DEPENDENCY,
+					   NULL);
+      else
+	{
+	  struct call_dl_lookup_args args;
+	  args.name = name;
+	  args.map = match;
+	  args.vers = vers;
+	  args.flags
+	    = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK;
+	  args.refp = &ref;
+
+	  THREAD_GSCOPE_SET_FLAG ();
+
+	  const char *objname;
+	  const char *errstring = NULL;
+	  bool malloced;
+	  int err = _dl_catch_error (&objname, &errstring, &malloced,
+				     call_dl_lookup, &args);
+
+	  THREAD_GSCOPE_RESET_FLAG ();
+
+	  if (__glibc_unlikely (errstring != NULL))
+	    {
+	      /* The lookup was unsuccessful.  Rethrow the error.  */
+	      char *errstring_dup = strdupa (errstring);
+	      char *objname_dup = strdupa (objname);
+	      if (malloced)
+		free ((char *) errstring);
+
+	      _dl_signal_error (err, objname_dup, NULL, errstring_dup);
+	      /* NOTREACHED */
+	    }
+
+	  result = args.map;
+	}
+    }
+  else if (handle == RTLD_NEXT)
+    {
+      if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded))
+	{
+	  if (match == NULL
+	      || caller < match->l_map_start
+	      || caller >= match->l_map_end)
+	    _dl_signal_error (0, NULL, NULL, N_("\
+RTLD_NEXT used in code not dynamically loaded"));
+	}
+
+      struct link_map *l = match;
+      while (l->l_loader != NULL)
+	l = l->l_loader;
+
+      result = GLRO(dl_lookup_symbol_x) (name, match, &ref, l->l_local_scope,
+					 vers, 0, 0, match);
+    }
+  else
+    {
+      /* Search the scope of the given object.  */
+      struct link_map *map = handle;
+      result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope,
+					 vers, 0, flags, NULL);
+    }
+
+  if (ref != NULL)
+    {
+      void *value;
+
+#ifdef SHARED
+      if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS)
+	/* The found symbol is a thread-local storage variable.
+	   Return the address for to the current thread.  */
+	value = _dl_tls_symaddr (result, ref);
+      else
+#endif
+	value = DL_SYMBOL_ADDRESS (result, ref);
+
+      /* Resolve indirect function address.  */
+      if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
+	{
+	  DL_FIXUP_VALUE_TYPE fixup
+	    = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
+	  fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
+	  value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
+	}
+
+#ifdef SHARED
+      /* Auditing checkpoint: we have a new binding.  Provide the
+	 auditing libraries the possibility to change the value and
+	 tell us whether further auditing is wanted.  */
+      if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+	{
+	  const char *strtab = (const char *) D_PTR (result,
+						     l_info[DT_STRTAB]);
+	  /* Compute index of the symbol entry in the symbol table of
+	     the DSO with the definition.  */
+	  unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
+							 l_info[DT_SYMTAB]));
+
+	  if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
+	    {
+	      unsigned int altvalue = 0;
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      /* Synthesize a symbol record where the st_value field is
+		 the result.  */
+	      ElfW(Sym) sym = *ref;
+	      sym.st_value = (ElfW(Addr)) value;
+
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  if (afct->symbind != NULL
+		      && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM)
+			  != 0
+			  || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO)
+			      != 0)))
+		    {
+		      unsigned int flags = altvalue | LA_SYMB_DLSYM;
+		      uintptr_t new_value
+			= afct->symbind (&sym, ndx,
+					 &match->l_audit[cnt].cookie,
+					 &result->l_audit[cnt].cookie,
+					 &flags, strtab + ref->st_name);
+		      if (new_value != (uintptr_t) sym.st_value)
+			{
+			  altvalue = LA_SYMB_ALTVALUE;
+			  sym.st_value = new_value;
+			}
+		    }
+
+		  afct = afct->next;
+		}
+
+	      value = (void *) sym.st_value;
+	    }
+	}
+#endif
+
+      return value;
+    }
+
+  return NULL;
+}
+
+
+void *
+internal_function
+_dl_vsym (void *handle, const char *name, const char *version, void *who)
+{
+  struct r_found_version vers;
+
+  /* Compute hash value to the version string.  */
+  vers.name = version;
+  vers.hidden = 1;
+  vers.hash = _dl_elf_hash (version);
+  /* We don't have a specific file where the symbol can be found.  */
+  vers.filename = NULL;
+
+  return do_sym (handle, name, who, &vers, 0);
+}
+
+
+void *
+internal_function
+_dl_sym (void *handle, const char *name, void *who)
+{
+  return do_sym (handle, name, who, NULL, DL_LOOKUP_RETURN_NEWEST);
+}
diff --git a/REORG.TODO/elf/dl-symaddr.c b/REORG.TODO/elf/dl-symaddr.c
new file mode 100644
index 0000000000..5caed4ba21
--- /dev/null
+++ b/REORG.TODO/elf/dl-symaddr.c
@@ -0,0 +1,33 @@
+/* Get the symbol address.  Generic version.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <dl-fptr.h>
+
+void *
+_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref)
+{
+  ElfW(Addr) value = (map ? map->l_addr : 0) + ref->st_value;
+
+  /* Return the pointer to function descriptor. */
+  if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC)
+    return (void *) _dl_make_fptr (map, ref, value);
+  else
+    return (void *) value;
+}
+rtld_hidden_def (_dl_symbol_address)
diff --git a/REORG.TODO/elf/dl-sysdep-open.h b/REORG.TODO/elf/dl-sysdep-open.h
new file mode 100644
index 0000000000..91851848b3
--- /dev/null
+++ b/REORG.TODO/elf/dl-sysdep-open.h
@@ -0,0 +1,45 @@
+/* System-specific call to open a shared object by name.  Stub version.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_SYSDEP_OPEN_H
+#define _DL_SYSDEP_OPEN_H	1
+
+#include <assert.h>
+#include <stddef.h>
+
+/* NAME is a name without slashes, as it appears in a DT_NEEDED entry
+   or a dlopen call's argument or suchlike.  NAMELEN is (strlen (NAME) + 1).
+
+   Find NAME in an OS-dependent fashion, and return its "real" name.
+   Optionally fill in *FD with a file descriptor open on that file (or
+   else leave its initial value of -1).  The return value is a new
+   malloc'd string, which will be free'd by the caller.  If NAME is
+   resolved to an actual file that can be opened, then the return
+   value should name that file (and if *FD was not set, then a normal
+   __open call on that string will be made).  If *FD was set by some
+   other means than a normal open and there is no "real" name to use,
+   then __strdup (NAME) is fine (modulo error checking).  */
+
+static inline char *
+_dl_sysdep_open_object (const char *name, size_t namelen, int *fd)
+{
+  assert (*fd == -1);
+  return NULL;
+}
+
+#endif  /* dl-sysdep-open.h */
diff --git a/REORG.TODO/elf/dl-sysdep.c b/REORG.TODO/elf/dl-sysdep.c
new file mode 100644
index 0000000000..4053ff3c07
--- /dev/null
+++ b/REORG.TODO/elf/dl-sysdep.c
@@ -0,0 +1,360 @@
+/* Operating system support for run-time dynamic linker.  Generic Unix version.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* We conditionalize the whole of this file rather than simply eliding it
+   from the static build, because other sysdeps/ versions of this file
+   might define things needed by a static build.  */
+
+#ifdef SHARED
+
+#include <assert.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <ldsodefs.h>
+#include <_itoa.h>
+#include <fpu_control.h>
+
+#include <entry.h>
+#include <dl-machine.h>
+#include <dl-procinfo.h>
+#include <dl-osinfo.h>
+#include <hp-timing.h>
+#include <tls.h>
+
+#include <dl-tunables.h>
+
+extern char **_environ attribute_hidden;
+extern char _end[] attribute_hidden;
+
+/* Protect SUID program against misuse of file descriptors.  */
+extern void __libc_check_standard_fds (void);
+
+#ifdef NEED_DL_BASE_ADDR
+ElfW(Addr) _dl_base_addr;
+#endif
+int __libc_enable_secure attribute_relro = 0;
+rtld_hidden_data_def (__libc_enable_secure)
+int __libc_multiple_libcs = 0;	/* Defining this here avoids the inclusion
+				   of init-first.  */
+/* This variable contains the lowest stack address ever used.  */
+void *__libc_stack_end attribute_relro = NULL;
+rtld_hidden_data_def(__libc_stack_end)
+void *_dl_random attribute_relro = NULL;
+
+#ifndef DL_FIND_ARG_COMPONENTS
+# define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp)	\
+  do {									      \
+    void **_tmp;							      \
+    (argc) = *(long int *) cookie;					      \
+    (argv) = (char **) ((long int *) cookie + 1);			      \
+    (envp) = (argv) + (argc) + 1;					      \
+    for (_tmp = (void **) (envp); *_tmp; ++_tmp)			      \
+      continue;								      \
+    (auxp) = (void *) ++_tmp;						      \
+  } while (0)
+#endif
+
+#ifndef DL_STACK_END
+# define DL_STACK_END(cookie) ((void *) (cookie))
+#endif
+
+ElfW(Addr)
+_dl_sysdep_start (void **start_argptr,
+		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
+				   ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
+{
+  const ElfW(Phdr) *phdr = NULL;
+  ElfW(Word) phnum = 0;
+  ElfW(Addr) user_entry;
+  ElfW(auxv_t) *av;
+#ifdef HAVE_AUX_SECURE
+# define set_seen(tag) (tag)	/* Evaluate for the side effects.  */
+# define set_seen_secure() ((void) 0)
+#else
+  uid_t uid = 0;
+  gid_t gid = 0;
+  unsigned int seen = 0;
+# define set_seen_secure() (seen = -1)
+# ifdef HAVE_AUX_XID
+#  define set_seen(tag) (tag)	/* Evaluate for the side effects.  */
+# else
+#  define M(type) (1 << (type))
+#  define set_seen(tag) seen |= M ((tag)->a_type)
+# endif
+#endif
+#ifdef NEED_DL_SYSINFO
+  uintptr_t new_sysinfo = 0;
+#endif
+
+  __libc_stack_end = DL_STACK_END (start_argptr);
+  DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
+			  GLRO(dl_auxv));
+
+  user_entry = (ElfW(Addr)) ENTRY_POINT;
+  GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
+
+  for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
+    switch (av->a_type)
+      {
+      case AT_PHDR:
+	phdr = (void *) av->a_un.a_val;
+	break;
+      case AT_PHNUM:
+	phnum = av->a_un.a_val;
+	break;
+      case AT_PAGESZ:
+	GLRO(dl_pagesize) = av->a_un.a_val;
+	break;
+      case AT_ENTRY:
+	user_entry = av->a_un.a_val;
+	break;
+#ifdef NEED_DL_BASE_ADDR
+      case AT_BASE:
+	_dl_base_addr = av->a_un.a_val;
+	break;
+#endif
+#ifndef HAVE_AUX_SECURE
+      case AT_UID:
+      case AT_EUID:
+	uid ^= av->a_un.a_val;
+	break;
+      case AT_GID:
+      case AT_EGID:
+	gid ^= av->a_un.a_val;
+	break;
+#endif
+      case AT_SECURE:
+#ifndef HAVE_AUX_SECURE
+	seen = -1;
+#endif
+	__libc_enable_secure = av->a_un.a_val;
+	break;
+      case AT_PLATFORM:
+	GLRO(dl_platform) = (void *) av->a_un.a_val;
+	break;
+      case AT_HWCAP:
+	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_HWCAP2:
+	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_CLKTCK:
+	GLRO(dl_clktck) = av->a_un.a_val;
+	break;
+      case AT_FPUCW:
+	GLRO(dl_fpu_control) = av->a_un.a_val;
+	break;
+#ifdef NEED_DL_SYSINFO
+      case AT_SYSINFO:
+	new_sysinfo = av->a_un.a_val;
+	break;
+#endif
+#ifdef NEED_DL_SYSINFO_DSO
+      case AT_SYSINFO_EHDR:
+	GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
+	break;
+#endif
+      case AT_RANDOM:
+	_dl_random = (void *) av->a_un.a_val;
+	break;
+#ifdef DL_PLATFORM_AUXV
+      DL_PLATFORM_AUXV
+#endif
+      }
+
+#ifndef HAVE_AUX_SECURE
+  if (seen != -1)
+    {
+      /* Fill in the values we have not gotten from the kernel through the
+	 auxiliary vector.  */
+# ifndef HAVE_AUX_XID
+#  define SEE(UID, var, uid) \
+   if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
+      SEE (UID, uid, uid);
+      SEE (EUID, uid, euid);
+      SEE (GID, gid, gid);
+      SEE (EGID, gid, egid);
+# endif
+
+      /* If one of the two pairs of IDs does not match this is a setuid
+	 or setgid run.  */
+      __libc_enable_secure = uid | gid;
+    }
+#endif
+
+#ifndef HAVE_AUX_PAGESIZE
+  if (GLRO(dl_pagesize) == 0)
+    GLRO(dl_pagesize) = __getpagesize ();
+#endif
+
+#ifdef NEED_DL_SYSINFO
+  if (new_sysinfo != 0)
+    {
+# ifdef NEED_DL_SYSINFO_DSO
+      /* Only set the sysinfo value if we also have the vsyscall DSO.  */
+      if (GLRO(dl_sysinfo_dso) != 0)
+# endif
+        GLRO(dl_sysinfo) = new_sysinfo;
+    }
+#endif
+
+  __tunables_init (_environ);
+
+#ifdef DL_SYSDEP_INIT
+  DL_SYSDEP_INIT;
+#endif
+
+#ifdef DL_PLATFORM_INIT
+  DL_PLATFORM_INIT;
+#endif
+
+  /* Determine the length of the platform name.  */
+  if (GLRO(dl_platform) != NULL)
+    GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
+
+  if (__sbrk (0) == _end)
+    /* The dynamic linker was run as a program, and so the initial break
+       starts just after our bss, at &_end.  The malloc in dl-minimal.c
+       will consume the rest of this page, so tell the kernel to move the
+       break up that far.  When the user program examines its break, it
+       will see this new value and not clobber our data.  */
+    __sbrk (GLRO(dl_pagesize)
+	    - ((_end - (char *) 0) & (GLRO(dl_pagesize) - 1)));
+
+  /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
+     allocated.  If necessary we are doing it ourself.  If it is not
+     possible we stop the program.  */
+  if (__builtin_expect (__libc_enable_secure, 0))
+    __libc_check_standard_fds ();
+
+  (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
+  return user_entry;
+}
+
+void
+internal_function
+_dl_sysdep_start_cleanup (void)
+{
+}
+
+void
+internal_function
+_dl_show_auxv (void)
+{
+  char buf[64];
+  ElfW(auxv_t) *av;
+
+  /* Terminate string.  */
+  buf[63] = '\0';
+
+  /* The following code assumes that the AT_* values are encoded
+     starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
+     close by (otherwise the array will be too large).  In case we have
+     to support a platform where these requirements are not fulfilled
+     some alternative implementation has to be used.  */
+  for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
+    {
+      static const struct
+      {
+	const char label[17];
+	enum { unknown = 0, dec, hex, str, ignore } form : 8;
+      } auxvars[] =
+	{
+	  [AT_EXECFD - 2] =		{ "EXECFD:       ", dec },
+	  [AT_EXECFN - 2] =		{ "EXECFN:       ", str },
+	  [AT_PHDR - 2] =		{ "PHDR:         0x", hex },
+	  [AT_PHENT - 2] =		{ "PHENT:        ", dec },
+	  [AT_PHNUM - 2] =		{ "PHNUM:        ", dec },
+	  [AT_PAGESZ - 2] =		{ "PAGESZ:       ", dec },
+	  [AT_BASE - 2] =		{ "BASE:         0x", hex },
+	  [AT_FLAGS - 2] =		{ "FLAGS:        0x", hex },
+	  [AT_ENTRY - 2] =		{ "ENTRY:        0x", hex },
+	  [AT_NOTELF - 2] =		{ "NOTELF:       ", hex },
+	  [AT_UID - 2] =		{ "UID:          ", dec },
+	  [AT_EUID - 2] =		{ "EUID:         ", dec },
+	  [AT_GID - 2] =		{ "GID:          ", dec },
+	  [AT_EGID - 2] =		{ "EGID:         ", dec },
+	  [AT_PLATFORM - 2] =		{ "PLATFORM:     ", str },
+	  [AT_HWCAP - 2] =		{ "HWCAP:        ", hex },
+	  [AT_CLKTCK - 2] =		{ "CLKTCK:       ", dec },
+	  [AT_FPUCW - 2] =		{ "FPUCW:        ", hex },
+	  [AT_DCACHEBSIZE - 2] =	{ "DCACHEBSIZE:  0x", hex },
+	  [AT_ICACHEBSIZE - 2] =	{ "ICACHEBSIZE:  0x", hex },
+	  [AT_UCACHEBSIZE - 2] =	{ "UCACHEBSIZE:  0x", hex },
+	  [AT_IGNOREPPC - 2] =		{ "IGNOREPPC", ignore },
+	  [AT_SECURE - 2] =		{ "SECURE:       ", dec },
+	  [AT_BASE_PLATFORM - 2] =	{ "BASE_PLATFORM:", str },
+	  [AT_SYSINFO - 2] =		{ "SYSINFO:      0x", hex },
+	  [AT_SYSINFO_EHDR - 2] =	{ "SYSINFO_EHDR: 0x", hex },
+	  [AT_RANDOM - 2] =		{ "RANDOM:       0x", hex },
+	  [AT_HWCAP2 - 2] =		{ "HWCAP2:       0x", hex },
+	};
+      unsigned int idx = (unsigned int) (av->a_type - 2);
+
+      if ((unsigned int) av->a_type < 2u
+	  || (idx < sizeof (auxvars) / sizeof (auxvars[0])
+	      && auxvars[idx].form == ignore))
+	continue;
+
+      assert (AT_NULL == 0);
+      assert (AT_IGNORE == 1);
+
+      if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2)
+	{
+	  /* These are handled in a special way per platform.  */
+	  if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
+	    continue;
+	}
+
+      if (idx < sizeof (auxvars) / sizeof (auxvars[0])
+	  && auxvars[idx].form != unknown)
+	{
+	  const char *val = (char *) av->a_un.a_val;
+
+	  if (__builtin_expect (auxvars[idx].form, dec) == dec)
+	    val = _itoa ((unsigned long int) av->a_un.a_val,
+			 buf + sizeof buf - 1, 10, 0);
+	  else if (__builtin_expect (auxvars[idx].form, hex) == hex)
+	    val = _itoa ((unsigned long int) av->a_un.a_val,
+			 buf + sizeof buf - 1, 16, 0);
+
+	  _dl_printf ("AT_%s%s\n", auxvars[idx].label, val);
+
+	  continue;
+	}
+
+      /* Unknown value: print a generic line.  */
+      char buf2[17];
+      buf2[sizeof (buf2) - 1] = '\0';
+      const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
+				buf2 + sizeof buf2 - 1, 16, 0);
+      const char *val =  _itoa ((unsigned long int) av->a_type,
+				buf + sizeof buf - 1, 16, 0);
+      _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
+    }
+}
+
+#endif
diff --git a/REORG.TODO/elf/dl-tls.c b/REORG.TODO/elf/dl-tls.c
new file mode 100644
index 0000000000..5aba33b3fa
--- /dev/null
+++ b/REORG.TODO/elf/dl-tls.c
@@ -0,0 +1,953 @@
+/* Thread-local storage handling in the ELF dynamic linker.  Generic version.
+   Copyright (C) 2002-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <libintl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <atomic.h>
+
+#include <tls.h>
+#include <dl-tls.h>
+#include <ldsodefs.h>
+
+/* Amount of excess space to allocate in the static TLS area
+   to allow dynamic loading of modules defining IE-model TLS data.  */
+#define TLS_STATIC_SURPLUS	64 + DL_NNS * 100
+
+
+/* Out-of-memory handler.  */
+static void
+__attribute__ ((__noreturn__))
+oom (void)
+{
+  _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
+}
+
+
+size_t
+internal_function
+_dl_next_tls_modid (void)
+{
+  size_t result;
+
+  if (__builtin_expect (GL(dl_tls_dtv_gaps), false))
+    {
+      size_t disp = 0;
+      struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list);
+
+      /* Note that this branch will never be executed during program
+	 start since there are no gaps at that time.  Therefore it
+	 does not matter that the dl_tls_dtv_slotinfo is not allocated
+	 yet when the function is called for the first times.
+
+	 NB: the offset +1 is due to the fact that DTV[0] is used
+	 for something else.  */
+      result = GL(dl_tls_static_nelem) + 1;
+      if (result <= GL(dl_tls_max_dtv_idx))
+	do
+	  {
+	    while (result - disp < runp->len)
+	      {
+		if (runp->slotinfo[result - disp].map == NULL)
+		  break;
+
+		++result;
+		assert (result <= GL(dl_tls_max_dtv_idx) + 1);
+	      }
+
+	    if (result - disp < runp->len)
+	      break;
+
+	    disp += runp->len;
+	  }
+	while ((runp = runp->next) != NULL);
+
+      if (result > GL(dl_tls_max_dtv_idx))
+	{
+	  /* The new index must indeed be exactly one higher than the
+	     previous high.  */
+	  assert (result == GL(dl_tls_max_dtv_idx) + 1);
+	  /* There is no gap anymore.  */
+	  GL(dl_tls_dtv_gaps) = false;
+
+	  goto nogaps;
+	}
+    }
+  else
+    {
+      /* No gaps, allocate a new entry.  */
+    nogaps:
+
+      result = ++GL(dl_tls_max_dtv_idx);
+    }
+
+  return result;
+}
+
+
+size_t
+internal_function
+_dl_count_modids (void)
+{
+  /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
+     we fail to load a module and unload it leaving a gap.  If we don't
+     have gaps then the number of modids is the current maximum so
+     return that.  */
+  if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
+    return GL(dl_tls_max_dtv_idx);
+
+  /* We have gaps and are forced to count the non-NULL entries.  */
+  size_t n = 0;
+  struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list);
+  while (runp != NULL)
+    {
+      for (size_t i = 0; i < runp->len; ++i)
+	if (runp->slotinfo[i].map != NULL)
+	  ++n;
+
+      runp = runp->next;
+    }
+
+  return n;
+}
+
+
+#ifdef SHARED
+void
+internal_function
+_dl_determine_tlsoffset (void)
+{
+  size_t max_align = TLS_TCB_ALIGN;
+  size_t freetop = 0;
+  size_t freebottom = 0;
+
+  /* The first element of the dtv slot info list is allocated.  */
+  assert (GL(dl_tls_dtv_slotinfo_list) != NULL);
+  /* There is at this point only one element in the
+     dl_tls_dtv_slotinfo_list list.  */
+  assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL);
+
+  struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+
+  /* Determining the offset of the various parts of the static TLS
+     block has several dependencies.  In addition we have to work
+     around bugs in some toolchains.
+
+     Each TLS block from the objects available at link time has a size
+     and an alignment requirement.  The GNU ld computes the alignment
+     requirements for the data at the positions *in the file*, though.
+     I.e, it is not simply possible to allocate a block with the size
+     of the TLS program header entry.  The data is layed out assuming
+     that the first byte of the TLS block fulfills
+
+       p_vaddr mod p_align == &TLS_BLOCK mod p_align
+
+     This means we have to add artificial padding at the beginning of
+     the TLS block.  These bytes are never used for the TLS data in
+     this module but the first byte allocated must be aligned
+     according to mod p_align == 0 so that the first byte of the TLS
+     block is aligned according to p_vaddr mod p_align.  This is ugly
+     and the linker can help by computing the offsets in the TLS block
+     assuming the first byte of the TLS block is aligned according to
+     p_align.
+
+     The extra space which might be allocated before the first byte of
+     the TLS block need not go unused.  The code below tries to use
+     that memory for the next TLS block.  This can work if the total
+     memory requirement for the next TLS block is smaller than the
+     gap.  */
+
+#if TLS_TCB_AT_TP
+  /* We simply start with zero.  */
+  size_t offset = 0;
+
+  for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
+    {
+      assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
+
+      size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset
+			  & (slotinfo[cnt].map->l_tls_align - 1));
+      size_t off;
+      max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align);
+
+      if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize)
+	{
+	  off = roundup (freetop + slotinfo[cnt].map->l_tls_blocksize
+			 - firstbyte, slotinfo[cnt].map->l_tls_align)
+		+ firstbyte;
+	  if (off <= freebottom)
+	    {
+	      freetop = off;
+
+	      /* XXX For some architectures we perhaps should store the
+		 negative offset.  */
+	      slotinfo[cnt].map->l_tls_offset = off;
+	      continue;
+	    }
+	}
+
+      off = roundup (offset + slotinfo[cnt].map->l_tls_blocksize - firstbyte,
+		     slotinfo[cnt].map->l_tls_align) + firstbyte;
+      if (off > offset + slotinfo[cnt].map->l_tls_blocksize
+		+ (freebottom - freetop))
+	{
+	  freetop = offset;
+	  freebottom = off - slotinfo[cnt].map->l_tls_blocksize;
+	}
+      offset = off;
+
+      /* XXX For some architectures we perhaps should store the
+	 negative offset.  */
+      slotinfo[cnt].map->l_tls_offset = off;
+    }
+
+  GL(dl_tls_static_used) = offset;
+  GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align)
+			    + TLS_TCB_SIZE);
+#elif TLS_DTV_AT_TP
+  /* The TLS blocks start right after the TCB.  */
+  size_t offset = TLS_TCB_SIZE;
+
+  for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
+    {
+      assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
+
+      size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset
+			  & (slotinfo[cnt].map->l_tls_align - 1));
+      size_t off;
+      max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align);
+
+      if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom)
+	{
+	  off = roundup (freebottom, slotinfo[cnt].map->l_tls_align);
+	  if (off - freebottom < firstbyte)
+	    off += slotinfo[cnt].map->l_tls_align;
+	  if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop)
+	    {
+	      slotinfo[cnt].map->l_tls_offset = off - firstbyte;
+	      freebottom = (off + slotinfo[cnt].map->l_tls_blocksize
+			    - firstbyte);
+	      continue;
+	    }
+	}
+
+      off = roundup (offset, slotinfo[cnt].map->l_tls_align);
+      if (off - offset < firstbyte)
+	off += slotinfo[cnt].map->l_tls_align;
+
+      slotinfo[cnt].map->l_tls_offset = off - firstbyte;
+      if (off - firstbyte - offset > freetop - freebottom)
+	{
+	  freebottom = offset;
+	  freetop = off - firstbyte;
+	}
+
+      offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte;
+    }
+
+  GL(dl_tls_static_used) = offset;
+  GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS,
+				    TLS_TCB_ALIGN);
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+  /* The alignment requirement for the static TLS block.  */
+  GL(dl_tls_static_align) = max_align;
+}
+#endif /* SHARED */
+
+static void *
+internal_function
+allocate_dtv (void *result)
+{
+  dtv_t *dtv;
+  size_t dtv_length;
+
+  /* We allocate a few more elements in the dtv than are needed for the
+     initial set of modules.  This should avoid in most cases expansions
+     of the dtv.  */
+  dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
+  dtv = calloc (dtv_length + 2, sizeof (dtv_t));
+  if (dtv != NULL)
+    {
+      /* This is the initial length of the dtv.  */
+      dtv[0].counter = dtv_length;
+
+      /* The rest of the dtv (including the generation counter) is
+	 Initialize with zero to indicate nothing there.  */
+
+      /* Add the dtv to the thread data structures.  */
+      INSTALL_DTV (result, dtv);
+    }
+  else
+    result = NULL;
+
+  return result;
+}
+
+
+/* Get size and alignment requirements of the static TLS block.  */
+void
+internal_function
+_dl_get_tls_static_info (size_t *sizep, size_t *alignp)
+{
+  *sizep = GL(dl_tls_static_size);
+  *alignp = GL(dl_tls_static_align);
+}
+
+/* Derive the location of the pointer to the start of the original
+   allocation (before alignment) from the pointer to the TCB.  */
+static inline void **
+tcb_to_pointer_to_free_location (void *tcb)
+{
+#if TLS_TCB_AT_TP
+  /* The TCB follows the TLS blocks, and the pointer to the front
+     follows the TCB.  */
+  void **original_pointer_location = tcb + TLS_TCB_SIZE;
+#elif TLS_DTV_AT_TP
+  /* The TCB comes first, preceded by the pre-TCB, and the pointer is
+     before that.  */
+  void **original_pointer_location = tcb - TLS_PRE_TCB_SIZE - sizeof (void *);
+#endif
+  return original_pointer_location;
+}
+
+void *
+internal_function
+_dl_allocate_tls_storage (void)
+{
+  void *result;
+  size_t size = GL(dl_tls_static_size);
+
+#if TLS_DTV_AT_TP
+  /* Memory layout is:
+     [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
+			  ^ This should be returned.  */
+  size += TLS_PRE_TCB_SIZE;
+#endif
+
+  /* Perform the allocation.  Reserve space for the required alignment
+     and the pointer to the original allocation.  */
+  size_t alignment = GL(dl_tls_static_align);
+  void *allocated = malloc (size + alignment + sizeof (void *));
+  if (__glibc_unlikely (allocated == NULL))
+    return NULL;
+
+  /* Perform alignment and allocate the DTV.  */
+#if TLS_TCB_AT_TP
+  /* The TCB follows the TLS blocks, which determine the alignment.
+     (TCB alignment requirements have been taken into account when
+     calculating GL(dl_tls_static_align).)  */
+  void *aligned = (void *) roundup ((uintptr_t) allocated, alignment);
+  result = aligned + size - TLS_TCB_SIZE;
+
+  /* Clear the TCB data structure.  We can't ask the caller (i.e.
+     libpthread) to do it, because we will initialize the DTV et al.  */
+  memset (result, '\0', TLS_TCB_SIZE);
+#elif TLS_DTV_AT_TP
+  /* Pre-TCB and TCB come before the TLS blocks.  The layout computed
+     in _dl_determine_tlsoffset assumes that the TCB is aligned to the
+     TLS block alignment, and not just the TLS blocks after it.  This
+     can leave an unused alignment gap between the TCB and the TLS
+     blocks.  */
+  result = (void *) roundup
+    (sizeof (void *) + TLS_PRE_TCB_SIZE + (uintptr_t) allocated,
+     alignment);
+
+  /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before
+     it.  We can't ask the caller (i.e. libpthread) to do it, because
+     we will initialize the DTV et al.  */
+  memset (result - TLS_PRE_TCB_SIZE, '\0', TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
+#endif
+
+  /* Record the value of the original pointer for later
+     deallocation.  */
+  *tcb_to_pointer_to_free_location (result) = allocated;
+
+  result = allocate_dtv (result);
+  if (result == NULL)
+    free (allocated);
+  return result;
+}
+
+
+#ifndef SHARED
+extern dtv_t _dl_static_dtv[];
+# define _dl_initial_dtv (&_dl_static_dtv[1])
+#endif
+
+static dtv_t *
+_dl_resize_dtv (dtv_t *dtv)
+{
+  /* Resize the dtv.  */
+  dtv_t *newp;
+  /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
+     other threads concurrently.  */
+  size_t newsize
+    = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS;
+  size_t oldsize = dtv[-1].counter;
+
+  if (dtv == GL(dl_initial_dtv))
+    {
+      /* This is the initial dtv that was either statically allocated in
+	 __libc_setup_tls or allocated during rtld startup using the
+	 dl-minimal.c malloc instead of the real malloc.  We can't free
+	 it, we have to abandon the old storage.  */
+
+      newp = malloc ((2 + newsize) * sizeof (dtv_t));
+      if (newp == NULL)
+	oom ();
+      memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
+    }
+  else
+    {
+      newp = realloc (&dtv[-1],
+		      (2 + newsize) * sizeof (dtv_t));
+      if (newp == NULL)
+	oom ();
+    }
+
+  newp[0].counter = newsize;
+
+  /* Clear the newly allocated part.  */
+  memset (newp + 2 + oldsize, '\0',
+	  (newsize - oldsize) * sizeof (dtv_t));
+
+  /* Return the generation counter.  */
+  return &newp[1];
+}
+
+
+void *
+internal_function
+_dl_allocate_tls_init (void *result)
+{
+  if (result == NULL)
+    /* The memory allocation failed.  */
+    return NULL;
+
+  dtv_t *dtv = GET_DTV (result);
+  struct dtv_slotinfo_list *listp;
+  size_t total = 0;
+  size_t maxgen = 0;
+
+  /* Check if the current dtv is big enough.   */
+  if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
+    {
+      /* Resize the dtv.  */
+      dtv = _dl_resize_dtv (dtv);
+
+      /* Install this new dtv in the thread data structures.  */
+      INSTALL_DTV (result, &dtv[-1]);
+    }
+
+  /* We have to prepare the dtv for all currently loaded modules using
+     TLS.  For those which are dynamically loaded we add the values
+     indicating deferred allocation.  */
+  listp = GL(dl_tls_dtv_slotinfo_list);
+  while (1)
+    {
+      size_t cnt;
+
+      for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+	{
+	  struct link_map *map;
+	  void *dest;
+
+	  /* Check for the total number of used slots.  */
+	  if (total + cnt > GL(dl_tls_max_dtv_idx))
+	    break;
+
+	  map = listp->slotinfo[cnt].map;
+	  if (map == NULL)
+	    /* Unused entry.  */
+	    continue;
+
+	  /* Keep track of the maximum generation number.  This might
+	     not be the generation counter.  */
+	  assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
+	  maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+
+	  dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+	  dtv[map->l_tls_modid].pointer.to_free = NULL;
+
+	  if (map->l_tls_offset == NO_TLS_OFFSET
+	      || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
+	    continue;
+
+	  assert (map->l_tls_modid == total + cnt);
+	  assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
+#if TLS_TCB_AT_TP
+	  assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
+	  dest = (char *) result - map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+	  dest = (char *) result + map->l_tls_offset;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+	  /* Set up the DTV entry.  The simplified __tls_get_addr that
+	     some platforms use in static programs requires it.  */
+	  dtv[map->l_tls_modid].pointer.val = dest;
+
+	  /* Copy the initialization image and clear the BSS part.  */
+	  memset (__mempcpy (dest, map->l_tls_initimage,
+			     map->l_tls_initimage_size), '\0',
+		  map->l_tls_blocksize - map->l_tls_initimage_size);
+	}
+
+      total += cnt;
+      if (total >= GL(dl_tls_max_dtv_idx))
+	break;
+
+      listp = listp->next;
+      assert (listp != NULL);
+    }
+
+  /* The DTV version is up-to-date now.  */
+  dtv[0].counter = maxgen;
+
+  return result;
+}
+rtld_hidden_def (_dl_allocate_tls_init)
+
+void *
+internal_function
+_dl_allocate_tls (void *mem)
+{
+  return _dl_allocate_tls_init (mem == NULL
+				? _dl_allocate_tls_storage ()
+				: allocate_dtv (mem));
+}
+rtld_hidden_def (_dl_allocate_tls)
+
+
+void
+internal_function
+_dl_deallocate_tls (void *tcb, bool dealloc_tcb)
+{
+  dtv_t *dtv = GET_DTV (tcb);
+
+  /* We need to free the memory allocated for non-static TLS.  */
+  for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
+    free (dtv[1 + cnt].pointer.to_free);
+
+  /* The array starts with dtv[-1].  */
+  if (dtv != GL(dl_initial_dtv))
+    free (dtv - 1);
+
+  if (dealloc_tcb)
+    free (*tcb_to_pointer_to_free_location (tcb));
+}
+rtld_hidden_def (_dl_deallocate_tls)
+
+
+#ifdef SHARED
+/* The __tls_get_addr function has two basic forms which differ in the
+   arguments.  The IA-64 form takes two parameters, the module ID and
+   offset.  The form used, among others, on IA-32 takes a reference to
+   a special structure which contain the same information.  The second
+   form seems to be more often used (in the moment) so we default to
+   it.  Users of the IA-64 form have to provide adequate definitions
+   of the following macros.  */
+# ifndef GET_ADDR_ARGS
+#  define GET_ADDR_ARGS tls_index *ti
+#  define GET_ADDR_PARAM ti
+# endif
+# ifndef GET_ADDR_MODULE
+#  define GET_ADDR_MODULE ti->ti_module
+# endif
+# ifndef GET_ADDR_OFFSET
+#  define GET_ADDR_OFFSET ti->ti_offset
+# endif
+
+/* Allocate one DTV entry.  */
+static struct dtv_pointer
+allocate_dtv_entry (size_t alignment, size_t size)
+{
+  if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
+    {
+      /* The alignment is supported by malloc.  */
+      void *ptr = malloc (size);
+      return (struct dtv_pointer) { ptr, ptr };
+    }
+
+  /* Emulate memalign to by manually aligning a pointer returned by
+     malloc.  First compute the size with an overflow check.  */
+  size_t alloc_size = size + alignment;
+  if (alloc_size < size)
+    return (struct dtv_pointer) {};
+
+  /* Perform the allocation.  This is the pointer we need to free
+     later.  */
+  void *start = malloc (alloc_size);
+  if (start == NULL)
+    return (struct dtv_pointer) {};
+
+  /* Find the aligned position within the larger allocation.  */
+  void *aligned = (void *) roundup ((uintptr_t) start, alignment);
+
+  return (struct dtv_pointer) { .val = aligned, .to_free = start };
+}
+
+static struct dtv_pointer
+allocate_and_init (struct link_map *map)
+{
+  struct dtv_pointer result = allocate_dtv_entry
+    (map->l_tls_align, map->l_tls_blocksize);
+  if (result.val == NULL)
+    oom ();
+
+  /* Initialize the memory.  */
+  memset (__mempcpy (result.val, map->l_tls_initimage,
+		     map->l_tls_initimage_size),
+	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+
+  return result;
+}
+
+
+struct link_map *
+_dl_update_slotinfo (unsigned long int req_modid)
+{
+  struct link_map *the_map = NULL;
+  dtv_t *dtv = THREAD_DTV ();
+
+  /* The global dl_tls_dtv_slotinfo array contains for each module
+     index the generation counter current when the entry was created.
+     This array never shrinks so that all module indices which were
+     valid at some time can be used to access it.  Before the first
+     use of a new module index in this function the array was extended
+     appropriately.  Access also does not have to be guarded against
+     modifications of the array.  It is assumed that pointer-size
+     values can be read atomically even in SMP environments.  It is
+     possible that other threads at the same time dynamically load
+     code and therefore add to the slotinfo list.  This is a problem
+     since we must not pick up any information about incomplete work.
+     The solution to this is to ignore all dtv slots which were
+     created after the one we are currently interested.  We know that
+     dynamic loading for this module is completed and this is the last
+     load operation we know finished.  */
+  unsigned long int idx = req_modid;
+  struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+  while (idx >= listp->len)
+    {
+      idx -= listp->len;
+      listp = listp->next;
+    }
+
+  if (dtv[0].counter < listp->slotinfo[idx].gen)
+    {
+      /* The generation counter for the slot is higher than what the
+	 current dtv implements.  We have to update the whole dtv but
+	 only those entries with a generation counter <= the one for
+	 the entry we need.  */
+      size_t new_gen = listp->slotinfo[idx].gen;
+      size_t total = 0;
+
+      /* We have to look through the entire dtv slotinfo list.  */
+      listp =  GL(dl_tls_dtv_slotinfo_list);
+      do
+	{
+	  for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+	    {
+	      size_t gen = listp->slotinfo[cnt].gen;
+
+	      if (gen > new_gen)
+		/* This is a slot for a generation younger than the
+		   one we are handling now.  It might be incompletely
+		   set up so ignore it.  */
+		continue;
+
+	      /* If the entry is older than the current dtv layout we
+		 know we don't have to handle it.  */
+	      if (gen <= dtv[0].counter)
+		continue;
+
+	      /* If there is no map this means the entry is empty.  */
+	      struct link_map *map = listp->slotinfo[cnt].map;
+	      if (map == NULL)
+		{
+		  if (dtv[-1].counter >= total + cnt)
+		    {
+		      /* If this modid was used at some point the memory
+			 might still be allocated.  */
+		      free (dtv[total + cnt].pointer.to_free);
+		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+		      dtv[total + cnt].pointer.to_free = NULL;
+		    }
+
+		  continue;
+		}
+
+	      /* Check whether the current dtv array is large enough.  */
+	      size_t modid = map->l_tls_modid;
+	      assert (total + cnt == modid);
+	      if (dtv[-1].counter < modid)
+		{
+		  /* Resize the dtv.  */
+		  dtv = _dl_resize_dtv (dtv);
+
+		  assert (modid <= dtv[-1].counter);
+
+		  /* Install this new dtv in the thread data
+		     structures.  */
+		  INSTALL_NEW_DTV (dtv);
+		}
+
+	      /* If there is currently memory allocate for this
+		 dtv entry free it.  */
+	      /* XXX Ideally we will at some point create a memory
+		 pool.  */
+	      free (dtv[modid].pointer.to_free);
+	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+	      dtv[modid].pointer.to_free = NULL;
+
+	      if (modid == req_modid)
+		the_map = map;
+	    }
+
+	  total += listp->len;
+	}
+      while ((listp = listp->next) != NULL);
+
+      /* This will be the new maximum generation counter.  */
+      dtv[0].counter = new_gen;
+    }
+
+  return the_map;
+}
+
+
+static void *
+__attribute_noinline__
+tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
+{
+  /* The allocation was deferred.  Do it now.  */
+  if (the_map == NULL)
+    {
+      /* Find the link map for this module.  */
+      size_t idx = GET_ADDR_MODULE;
+      struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+      while (idx >= listp->len)
+	{
+	  idx -= listp->len;
+	  listp = listp->next;
+	}
+
+      the_map = listp->slotinfo[idx].map;
+    }
+
+  /* Make sure that, if a dlopen running in parallel forces the
+     variable into static storage, we'll wait until the address in the
+     static TLS block is set up, and use that.  If we're undecided
+     yet, make sure we make the decision holding the lock as well.  */
+  if (__glibc_unlikely (the_map->l_tls_offset
+			!= FORCED_DYNAMIC_TLS_OFFSET))
+    {
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+      if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
+	{
+	  the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
+	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+	}
+      else if (__glibc_likely (the_map->l_tls_offset
+			       != FORCED_DYNAMIC_TLS_OFFSET))
+	{
+#if TLS_TCB_AT_TP
+	  void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+	  void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+	  dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
+	  dtv[GET_ADDR_MODULE].pointer.val = p;
+
+	  return (char *) p + GET_ADDR_OFFSET;
+	}
+      else
+	__rtld_lock_unlock_recursive (GL(dl_load_lock));
+    }
+  struct dtv_pointer result = allocate_and_init (the_map);
+  dtv[GET_ADDR_MODULE].pointer = result;
+  assert (result.to_free != NULL);
+
+  return (char *) result.val + GET_ADDR_OFFSET;
+}
+
+
+static struct link_map *
+__attribute_noinline__
+update_get_addr (GET_ADDR_ARGS)
+{
+  struct link_map *the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+  dtv_t *dtv = THREAD_DTV ();
+
+  void *p = dtv[GET_ADDR_MODULE].pointer.val;
+
+  if (__glibc_unlikely (p == TLS_DTV_UNALLOCATED))
+    return tls_get_addr_tail (GET_ADDR_PARAM, dtv, the_map);
+
+  return (void *) p + GET_ADDR_OFFSET;
+}
+
+/* For all machines that have a non-macro version of __tls_get_addr, we
+   want to use rtld_hidden_proto/rtld_hidden_def in order to call the
+   internal alias for __tls_get_addr from ld.so. This avoids a PLT entry
+   in ld.so for __tls_get_addr.  */
+
+#ifndef __tls_get_addr
+extern void * __tls_get_addr (GET_ADDR_ARGS);
+rtld_hidden_proto (__tls_get_addr)
+rtld_hidden_def (__tls_get_addr)
+#endif
+
+/* The generic dynamic and local dynamic model cannot be used in
+   statically linked applications.  */
+void *
+__tls_get_addr (GET_ADDR_ARGS)
+{
+  dtv_t *dtv = THREAD_DTV ();
+
+  if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
+    return update_get_addr (GET_ADDR_PARAM);
+
+  void *p = dtv[GET_ADDR_MODULE].pointer.val;
+
+  if (__glibc_unlikely (p == TLS_DTV_UNALLOCATED))
+    return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
+
+  return (char *) p + GET_ADDR_OFFSET;
+}
+#endif
+
+
+/* Look up the module's TLS block as for __tls_get_addr,
+   but never touch anything.  Return null if it's not allocated yet.  */
+void *
+_dl_tls_get_addr_soft (struct link_map *l)
+{
+  if (__glibc_unlikely (l->l_tls_modid == 0))
+    /* This module has no TLS segment.  */
+    return NULL;
+
+  dtv_t *dtv = THREAD_DTV ();
+  if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
+    {
+      /* This thread's DTV is not completely current,
+	 but it might already cover this module.  */
+
+      if (l->l_tls_modid >= dtv[-1].counter)
+	/* Nope.  */
+	return NULL;
+
+      size_t idx = l->l_tls_modid;
+      struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+      while (idx >= listp->len)
+	{
+	  idx -= listp->len;
+	  listp = listp->next;
+	}
+
+      /* We've reached the slot for this module.
+	 If its generation counter is higher than the DTV's,
+	 this thread does not know about this module yet.  */
+      if (dtv[0].counter < listp->slotinfo[idx].gen)
+	return NULL;
+    }
+
+  void *data = dtv[l->l_tls_modid].pointer.val;
+  if (__glibc_unlikely (data == TLS_DTV_UNALLOCATED))
+    /* The DTV is current, but this thread has not yet needed
+       to allocate this module's segment.  */
+    data = NULL;
+
+  return data;
+}
+
+
+void
+_dl_add_to_slotinfo (struct link_map *l)
+{
+  /* Now that we know the object is loaded successfully add
+     modules containing TLS data to the dtv info table.  We
+     might have to increase its size.  */
+  struct dtv_slotinfo_list *listp;
+  struct dtv_slotinfo_list *prevp;
+  size_t idx = l->l_tls_modid;
+
+  /* Find the place in the dtv slotinfo list.  */
+  listp = GL(dl_tls_dtv_slotinfo_list);
+  prevp = NULL;		/* Needed to shut up gcc.  */
+  do
+    {
+      /* Does it fit in the array of this list element?  */
+      if (idx < listp->len)
+	break;
+      idx -= listp->len;
+      prevp = listp;
+      listp = listp->next;
+    }
+  while (listp != NULL);
+
+  if (listp == NULL)
+    {
+      /* When we come here it means we have to add a new element
+	 to the slotinfo list.  And the new module must be in
+	 the first slot.  */
+      assert (idx == 0);
+
+      listp = prevp->next = (struct dtv_slotinfo_list *)
+	malloc (sizeof (struct dtv_slotinfo_list)
+		+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+      if (listp == NULL)
+	{
+	  /* We ran out of memory.  We will simply fail this
+	     call but don't undo anything we did so far.  The
+	     application will crash or be terminated anyway very
+	     soon.  */
+
+	  /* We have to do this since some entries in the dtv
+	     slotinfo array might already point to this
+	     generation.  */
+	  ++GL(dl_tls_generation);
+
+	  _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\
+cannot create TLS data structures"));
+	}
+
+      listp->len = TLS_SLOTINFO_SURPLUS;
+      listp->next = NULL;
+      memset (listp->slotinfo, '\0',
+	      TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+    }
+
+  /* Add the information into the slotinfo data structure.  */
+  listp->slotinfo[idx].map = l;
+  listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
+}
diff --git a/REORG.TODO/elf/dl-trampoline.c b/REORG.TODO/elf/dl-trampoline.c
new file mode 100644
index 0000000000..3ca89f3879
--- /dev/null
+++ b/REORG.TODO/elf/dl-trampoline.c
@@ -0,0 +1 @@
+#error "Architecture specific PLT trampolines must be defined."
diff --git a/REORG.TODO/elf/dl-tunable-types.h b/REORG.TODO/elf/dl-tunable-types.h
new file mode 100644
index 0000000000..1d516df08f
--- /dev/null
+++ b/REORG.TODO/elf/dl-tunable-types.h
@@ -0,0 +1,62 @@
+/* Tunable type information.
+
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TUNABLE_TYPES_H_
+# define _TUNABLE_TYPES_H_
+#include <stddef.h>
+
+typedef enum
+{
+  TUNABLE_TYPE_INT_32,
+  TUNABLE_TYPE_UINT_64,
+  TUNABLE_TYPE_SIZE_T,
+  TUNABLE_TYPE_STRING
+} tunable_type_code_t;
+
+typedef struct
+{
+  tunable_type_code_t type_code;
+  int64_t min;
+  int64_t max;
+} tunable_type_t;
+
+typedef union
+{
+  int64_t numval;
+  const char *strval;
+} tunable_val_t;
+
+typedef void (*tunable_callback_t) (tunable_val_t *);
+
+/* Security level for tunables.  This decides what to do with individual
+   tunables for AT_SECURE binaries.  */
+typedef enum
+{
+  /* Erase the tunable for AT_SECURE binaries so that child processes don't
+     read it.  */
+  TUNABLE_SECLEVEL_SXID_ERASE = 0,
+  /* Ignore the tunable for AT_SECURE binaries, but don't erase it, so that
+     child processes can read it.  */
+  TUNABLE_SECLEVEL_SXID_IGNORE = 1,
+  /* Read the tunable.  */
+  TUNABLE_SECLEVEL_NONE = 2,
+} tunable_seclevel_t;
+
+
+#endif
diff --git a/REORG.TODO/elf/dl-tunables.c b/REORG.TODO/elf/dl-tunables.c
new file mode 100644
index 0000000000..76e8c5cae1
--- /dev/null
+++ b/REORG.TODO/elf/dl-tunables.c
@@ -0,0 +1,490 @@
+/* The tunable framework.  See the README.tunables to know how to use the
+   tunable in a glibc module.
+
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sysdep.h>
+#include <fcntl.h>
+#include <ldsodefs.h>
+
+#define TUNABLES_INTERNAL 1
+#include "dl-tunables.h"
+
+#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
+# define GLIBC_TUNABLES "GLIBC_TUNABLES"
+#endif
+
+/* Compare environment or tunable names, bounded by the name hardcoded in
+   glibc.  */
+static bool
+is_name (const char *orig, const char *envname)
+{
+  for (;*orig != '\0' && *envname != '\0'; envname++, orig++)
+    if (*orig != *envname)
+      break;
+
+  /* The ENVNAME is immediately followed by a value.  */
+  if (*orig == '\0' && *envname == '=')
+    return true;
+  else
+    return false;
+}
+
+#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
+static char *
+tunables_strdup (const char *in)
+{
+  size_t i = 0;
+
+  while (in[i++] != '\0');
+  char *out = __sbrk (i);
+
+  /* FIXME: In reality if the allocation fails, __sbrk will crash attempting to
+     set the thread-local errno since the TCB has not yet been set up.  This
+     needs to be fixed with an __sbrk implementation that does not set
+     errno.  */
+  if (out == (void *)-1)
+    return NULL;
+
+  i--;
+
+  while (i-- > 0)
+    out[i] = in[i];
+
+  return out;
+}
+#endif
+
+static char **
+get_next_env (char **envp, char **name, size_t *namelen, char **val,
+	      char ***prev_envp)
+{
+  while (envp != NULL && *envp != NULL)
+    {
+      char **prev = envp;
+      char *envline = *envp++;
+      int len = 0;
+
+      while (envline[len] != '\0' && envline[len] != '=')
+	len++;
+
+      /* Just the name and no value, go to the next one.  */
+      if (envline[len] == '\0')
+	continue;
+
+      *name = envline;
+      *namelen = len;
+      *val = &envline[len + 1];
+      *prev_envp = prev;
+
+      return envp;
+    }
+
+  return NULL;
+}
+
+/* A stripped down strtoul-like implementation for very early use.  It does not
+   set errno if the result is outside bounds because it gets called before
+   errno may have been set up.  */
+static uint64_t
+tunables_strtoul (const char *nptr)
+{
+  uint64_t result = 0;
+  long int sign = 1;
+  unsigned max_digit;
+
+  while (*nptr == ' ' || *nptr == '\t')
+    ++nptr;
+
+  if (*nptr == '-')
+    {
+      sign = -1;
+      ++nptr;
+    }
+  else if (*nptr == '+')
+    ++nptr;
+
+  if (*nptr < '0' || *nptr > '9')
+    return 0UL;
+
+  int base = 10;
+  max_digit = 9;
+  if (*nptr == '0')
+    {
+      if (nptr[1] == 'x' || nptr[1] == 'X')
+	{
+	  base = 16;
+	  nptr += 2;
+	}
+      else
+	{
+	  base = 8;
+	  max_digit = 7;
+	}
+    }
+
+  while (1)
+    {
+      int digval;
+      if (*nptr >= '0' && *nptr <= '0' + max_digit)
+        digval = *nptr - '0';
+      else if (base == 16)
+        {
+	  if (*nptr >= 'a' && *nptr <= 'f')
+	    digval = *nptr - 'a' + 10;
+	  else if (*nptr >= 'A' && *nptr <= 'F')
+	    digval = *nptr - 'A' + 10;
+	  else
+	    break;
+	}
+      else
+        break;
+
+      if (result >= (UINT64_MAX - digval) / base)
+	return UINT64_MAX;
+      result *= base;
+      result += digval;
+      ++nptr;
+    }
+
+  return result * sign;
+}
+
+#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type, __default_min, \
+				       __default_max)			      \
+({									      \
+  __type min = (__cur)->type.min;					      \
+  __type max = (__cur)->type.max;					      \
+									      \
+  if (min == max)							      \
+    {									      \
+      min = __default_min;						      \
+      max = __default_max;						      \
+    }									      \
+									      \
+  if ((__type) (__val) >= min && (__type) (val) <= max)			      \
+    {									      \
+      (__cur)->val.numval = val;					      \
+      (__cur)->initialized = true;					      \
+    }									      \
+})
+
+static void
+do_tunable_update_val (tunable_t *cur, const void *valp)
+{
+  uint64_t val;
+
+  if (cur->type.type_code != TUNABLE_TYPE_STRING)
+    val = *((int64_t *) valp);
+
+  switch (cur->type.type_code)
+    {
+    case TUNABLE_TYPE_INT_32:
+	{
+	  TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t, INT32_MIN, INT32_MAX);
+	  break;
+	}
+    case TUNABLE_TYPE_UINT_64:
+	{
+	  TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, UINT64_MAX);
+	  break;
+	}
+    case TUNABLE_TYPE_SIZE_T:
+	{
+	  TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, SIZE_MAX);
+	  break;
+	}
+    case TUNABLE_TYPE_STRING:
+	{
+	  cur->val.strval = valp;
+	  break;
+	}
+    default:
+      __builtin_unreachable ();
+    }
+}
+
+/* Validate range of the input value and initialize the tunable CUR if it looks
+   good.  */
+static void
+tunable_initialize (tunable_t *cur, const char *strval)
+{
+  uint64_t val;
+  const void *valp;
+
+  if (cur->type.type_code != TUNABLE_TYPE_STRING)
+    {
+      val = tunables_strtoul (strval);
+      valp = &val;
+    }
+  else
+    {
+      cur->initialized = true;
+      valp = strval;
+    }
+  do_tunable_update_val (cur, valp);
+}
+
+void
+__tunable_set_val (tunable_id_t id, void *valp)
+{
+  tunable_t *cur = &tunable_list[id];
+
+  do_tunable_update_val (cur, valp);
+}
+
+#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
+/* Parse the tunable string TUNESTR and adjust it to drop any tunables that may
+   be unsafe for AT_SECURE processes so that it can be used as the new
+   environment variable value for GLIBC_TUNABLES.  VALSTRING is the original
+   environment variable string which we use to make NULL terminated values so
+   that we don't have to allocate memory again for it.  */
+static void
+parse_tunables (char *tunestr, char *valstring)
+{
+  if (tunestr == NULL || *tunestr == '\0')
+    return;
+
+  char *p = tunestr;
+
+  while (true)
+    {
+      char *name = p;
+      size_t len = 0;
+
+      /* First, find where the name ends.  */
+      while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
+	len++;
+
+      /* If we reach the end of the string before getting a valid name-value
+	 pair, bail out.  */
+      if (p[len] == '\0')
+	return;
+
+      /* We did not find a valid name-value pair before encountering the
+	 colon.  */
+      if (p[len]== ':')
+	{
+	  p += len + 1;
+	  continue;
+	}
+
+      p += len + 1;
+
+      /* Take the value from the valstring since we need to NULL terminate it.  */
+      char *value = &valstring[p - tunestr];
+      len = 0;
+
+      while (p[len] != ':' && p[len] != '\0')
+	len++;
+
+      /* Add the tunable if it exists.  */
+      for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+	{
+	  tunable_t *cur = &tunable_list[i];
+
+	  if (is_name (cur->name, name))
+	    {
+	      /* If we are in a secure context (AT_SECURE) then ignore the tunable
+		 unless it is explicitly marked as secure.  Tunable values take
+		 precendence over their envvar aliases.  */
+	      if (__libc_enable_secure)
+		{
+		  if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
+		    {
+		      if (p[len] == '\0')
+			{
+			  /* Last tunable in the valstring.  Null-terminate and
+			     return.  */
+			  *name = '\0';
+			  return;
+			}
+		      else
+			{
+			  /* Remove the current tunable from the string.  We do
+			     this by overwriting the string starting from NAME
+			     (which is where the current tunable begins) with
+			     the remainder of the string.  We then have P point
+			     to NAME so that we continue in the correct
+			     position in the valstring.  */
+			  char *q = &p[len + 1];
+			  p = name;
+			  while (*q != '\0')
+			    *name++ = *q++;
+			  name[0] = '\0';
+			  len = 0;
+			}
+		    }
+
+		  if (cur->security_level != TUNABLE_SECLEVEL_NONE)
+		    break;
+		}
+
+	      value[len] = '\0';
+	      tunable_initialize (cur, value);
+	      break;
+	    }
+	}
+
+      if (p[len] == '\0')
+	return;
+      else
+	p += len + 1;
+    }
+}
+#endif
+
+/* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when
+   the system administrator has created the /etc/suid-debug file.  This is a
+   special case where we want to conditionally enable/disable a tunable even
+   for setuid binaries.  We use the special version of access() to avoid
+   setting ERRNO, which is a TLS variable since TLS has not yet been set
+   up.  */
+static inline void
+__always_inline
+maybe_enable_malloc_check (void)
+{
+  tunable_id_t id = TUNABLE_ENUM_NAME (glibc, malloc, check);
+  if (__libc_enable_secure && __access_noerrno ("/etc/suid-debug", F_OK) == 0)
+    tunable_list[id].security_level = TUNABLE_SECLEVEL_NONE;
+}
+
+/* Initialize the tunables list from the environment.  For now we only use the
+   ENV_ALIAS to find values.  Later we will also use the tunable names to find
+   values.  */
+void
+__tunables_init (char **envp)
+{
+  char *envname = NULL;
+  char *envval = NULL;
+  size_t len = 0;
+  char **prev_envp = envp;
+
+  maybe_enable_malloc_check ();
+
+  while ((envp = get_next_env (envp, &envname, &len, &envval,
+			       &prev_envp)) != NULL)
+    {
+#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
+      if (is_name (GLIBC_TUNABLES, envname))
+	{
+	  char *new_env = tunables_strdup (envname);
+	  if (new_env != NULL)
+	    parse_tunables (new_env + len + 1, envval);
+	  /* Put in the updated envval.  */
+	  *prev_envp = new_env;
+	  continue;
+	}
+#endif
+
+      for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+	{
+	  tunable_t *cur = &tunable_list[i];
+
+	  /* Skip over tunables that have either been set already or should be
+	     skipped.  */
+	  if (cur->initialized || cur->env_alias == NULL)
+	    continue;
+
+	  const char *name = cur->env_alias;
+
+	  /* We have a match.  Initialize and move on to the next line.  */
+	  if (is_name (name, envname))
+	    {
+	      /* For AT_SECURE binaries, we need to check the security settings of
+		 the tunable and decide whether we read the value and also whether
+		 we erase the value so that child processes don't inherit them in
+		 the environment.  */
+	      if (__libc_enable_secure)
+		{
+		  if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
+		    {
+		      /* Erase the environment variable.  */
+		      char **ep = prev_envp;
+
+		      while (*ep != NULL)
+			{
+			  if (is_name (name, *ep))
+			    {
+			      char **dp = ep;
+
+			      do
+				dp[0] = dp[1];
+			      while (*dp++);
+			    }
+			  else
+			    ++ep;
+			}
+		      /* Reset the iterator so that we read the environment again
+			 from the point we erased.  */
+		      envp = prev_envp;
+		    }
+
+		  if (cur->security_level != TUNABLE_SECLEVEL_NONE)
+		    continue;
+		}
+
+	      tunable_initialize (cur, envval);
+	      break;
+	    }
+	}
+    }
+}
+
+/* Set the tunable value.  This is called by the module that the tunable exists
+   in. */
+void
+__tunable_get_val (tunable_id_t id, void *valp, tunable_callback_t callback)
+{
+  tunable_t *cur = &tunable_list[id];
+
+  switch (cur->type.type_code)
+    {
+    case TUNABLE_TYPE_UINT_64:
+	{
+	  *((uint64_t *) valp) = (uint64_t) cur->val.numval;
+	  break;
+	}
+    case TUNABLE_TYPE_INT_32:
+	{
+	  *((int32_t *) valp) = (int32_t) cur->val.numval;
+	  break;
+	}
+    case TUNABLE_TYPE_SIZE_T:
+	{
+	  *((size_t *) valp) = (size_t) cur->val.numval;
+	  break;
+	}
+    case TUNABLE_TYPE_STRING:
+	{
+	  *((const char **)valp) = cur->val.strval;
+	  break;
+	}
+    default:
+      __builtin_unreachable ();
+    }
+
+  if (cur->initialized && callback != NULL)
+    callback (&cur->val);
+}
+
+rtld_hidden_def (__tunable_get_val)
diff --git a/REORG.TODO/elf/dl-tunables.h b/REORG.TODO/elf/dl-tunables.h
new file mode 100644
index 0000000000..6c49dcbf47
--- /dev/null
+++ b/REORG.TODO/elf/dl-tunables.h
@@ -0,0 +1,115 @@
+/* The tunable framework.  See the README to know how to use the tunable in
+   a glibc module.
+
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TUNABLES_H_
+#define _TUNABLES_H_
+
+#if !HAVE_TUNABLES
+static inline void
+__always_inline
+__tunables_init (char **unused __attribute__ ((unused)))
+{
+  /* This is optimized out if tunables are not enabled.  */
+}
+#else
+
+# include <stddef.h>
+# include "dl-tunable-types.h"
+
+/* A tunable.  */
+struct _tunable
+{
+  const char *name;			/* Internal name of the tunable.  */
+  tunable_type_t type;			/* Data type of the tunable.  */
+  tunable_val_t val;			/* The value.  */
+  bool initialized;			/* Flag to indicate that the tunable is
+					   initialized.  */
+  tunable_seclevel_t security_level;	/* Specify the security level for the
+					   tunable with respect to AT_SECURE
+					   programs.  See description of
+					   tunable_seclevel_t to see a
+					   description of the values.
+
+					   Note that even if the tunable is
+					   read, it may not get used by the
+					   target module if the value is
+					   considered unsafe.  */
+  /* Compatibility elements.  */
+  const char *env_alias;		/* The compatibility environment
+					   variable name.  */
+};
+
+typedef struct _tunable tunable_t;
+
+/* Full name for a tunable is top_ns.tunable_ns.id.  */
+# define TUNABLE_NAME_S(top,ns,id) #top "." #ns "." #id
+
+# define TUNABLE_ENUM_NAME(__top,__ns,__id) TUNABLE_ENUM_NAME1 (__top,__ns,__id)
+# define TUNABLE_ENUM_NAME1(__top,__ns,__id) __top ## _ ## __ns ## _ ## __id
+
+# include "dl-tunable-list.h"
+
+extern void __tunables_init (char **);
+extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
+extern void __tunable_set_val (tunable_id_t, void *);
+rtld_hidden_proto (__tunables_init)
+rtld_hidden_proto (__tunable_get_val)
+
+/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
+   TUNABLE_NAMESPACE are defined.  This is useful shorthand to get and set
+   tunables within a module.  */
+#if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE
+# define TUNABLE_GET(__id, __type, __cb) \
+  TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
+# define TUNABLE_SET(__id, __type, __val) \
+  TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __val)
+#else
+# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
+  TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
+# define TUNABLE_SET(__top, __ns, __id, __type, __val) \
+  TUNABLE_SET_FULL (__top, __ns, __id, __type, __val)
+#endif
+
+/* Get and return a tunable value.  If the tunable was set externally and __CB
+   is defined then call __CB before returning the value.  */
+# define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \
+({									      \
+  tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id);		      \
+  __type ret;								      \
+  __tunable_get_val (id, &ret, __cb);					      \
+  ret;									      \
+})
+
+/* Set a tunable value.  */
+# define TUNABLE_SET_FULL(__top, __ns, __id, __type, __val) \
+({									      \
+  __tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id),		      \
+			& (__type) {__val});				      \
+})
+
+/* Namespace sanity for callback functions.  Use this macro to keep the
+   namespace of the modules clean.  */
+# define TUNABLE_CALLBACK(__name) _dl_tunable_ ## __name
+
+# define TUNABLES_FRONTEND_valstring 1
+/* The default value for TUNABLES_FRONTEND.  */
+# define TUNABLES_FRONTEND_yes TUNABLES_FRONTEND_valstring
+#endif
+#endif
diff --git a/REORG.TODO/elf/dl-tunables.list b/REORG.TODO/elf/dl-tunables.list
new file mode 100644
index 0000000000..41ce9afa28
--- /dev/null
+++ b/REORG.TODO/elf/dl-tunables.list
@@ -0,0 +1,87 @@
+# Copyright (C) 2016-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# Allowed attributes for tunables:
+#
+# type: Defaults to STRING
+# minval: Optional minimum acceptable value
+# maxval: Optional maximum acceptable value
+# env_alias: An alias environment variable
+# security_level: Specify security level of the tunable.  Valid values are:
+#
+# 	     SXID_ERASE: (default) Don't read for AT_SECURE binaries and
+# 	     		 removed so that child processes can't read it.
+# 	     SXID_IGNORE: Don't read for AT_SECURE binaries, but retained for
+# 	     		  non-AT_SECURE subprocesses.
+# 	     NONE: Read all the time.
+
+glibc {
+  malloc {
+    check {
+      type: INT_32
+      minval: 0
+      maxval: 3
+      env_alias: MALLOC_CHECK_
+    }
+    top_pad {
+      type: SIZE_T
+      env_alias: MALLOC_TOP_PAD_
+      security_level: SXID_IGNORE
+    }
+    perturb {
+      type: INT_32
+      minval: 0
+      maxval: 0xff
+      env_alias: MALLOC_PERTURB_
+      security_level: SXID_IGNORE
+    }
+    mmap_threshold {
+      type: SIZE_T
+      env_alias: MALLOC_MMAP_THRESHOLD_
+      security_level: SXID_IGNORE
+    }
+    trim_threshold {
+      type: SIZE_T
+      env_alias: MALLOC_TRIM_THRESHOLD_
+      security_level: SXID_IGNORE
+    }
+    mmap_max {
+      type: INT_32
+      env_alias: MALLOC_MMAP_MAX_
+      security_level: SXID_IGNORE
+    }
+    arena_max {
+      type: SIZE_T
+      env_alias: MALLOC_ARENA_MAX
+      minval: 1
+      security_level: SXID_IGNORE
+    }
+    arena_test {
+      type: SIZE_T
+      env_alias: MALLOC_ARENA_TEST
+      minval: 1
+      security_level: SXID_IGNORE
+    }
+  }
+  tune {
+    hwcap_mask {
+      type: UINT_64
+      env_alias: LD_HWCAP_MASK
+      default: HWCAP_IMPORTANT
+    }
+  }
+}
diff --git a/REORG.TODO/elf/dl-unmap-segments.h b/REORG.TODO/elf/dl-unmap-segments.h
new file mode 100644
index 0000000000..f37e183943
--- /dev/null
+++ b/REORG.TODO/elf/dl-unmap-segments.h
@@ -0,0 +1,35 @@
+/* Unmap a shared object's segments.  Generic version.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_UNMAP_SEGMENTS_H
+#define _DL_UNMAP_SEGMENTS_H	1
+
+#include <link.h>
+#include <sys/mman.h>
+
+/* _dl_map_segments ensures that any whole pages in gaps between segments
+   are filled in with PROT_NONE mappings.  So we can just unmap the whole
+   range in one fell swoop.  */
+
+static __always_inline void
+_dl_unmap_segments (struct link_map *l)
+{
+  __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start);
+}
+
+#endif  /* dl-unmap-segments.h */
diff --git a/REORG.TODO/elf/dl-version.c b/REORG.TODO/elf/dl-version.c
new file mode 100644
index 0000000000..c00078e5e4
--- /dev/null
+++ b/REORG.TODO/elf/dl-version.c
@@ -0,0 +1,389 @@
+/* Handle symbol and library versioning.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <errno.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ldsodefs.h>
+#include <_itoa.h>
+
+#include <assert.h>
+
+
+#define make_string(string, rest...) \
+  ({									      \
+    const char *all[] = { string, ## rest };				      \
+    size_t len, cnt;							      \
+    char *result, *cp;							      \
+									      \
+    len = 1;								      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      len += strlen (all[cnt]);						      \
+									      \
+    cp = result = alloca (len);						      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      cp = __stpcpy (cp, all[cnt]);					      \
+									      \
+    result;								      \
+  })
+
+
+static inline struct link_map *
+__attribute ((always_inline))
+find_needed (const char *name, struct link_map *map)
+{
+  struct link_map *tmap;
+  unsigned int n;
+
+  for (tmap = GL(dl_ns)[map->l_ns]._ns_loaded; tmap != NULL;
+       tmap = tmap->l_next)
+    if (_dl_name_match_p (name, tmap))
+      return tmap;
+
+  /* The required object is not in the global scope, look to see if it is
+     a dependency of the current object.  */
+  for (n = 0; n < map->l_searchlist.r_nlist; n++)
+    if (_dl_name_match_p (name, map->l_searchlist.r_list[n]))
+      return map->l_searchlist.r_list[n];
+
+  /* Should never happen.  */
+  return NULL;
+}
+
+
+static int
+internal_function
+match_symbol (const char *name, Lmid_t ns, ElfW(Word) hash, const char *string,
+	      struct link_map *map, int verbose, int weak)
+{
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+  ElfW(Addr) def_offset;
+  ElfW(Verdef) *def;
+  /* Initialize to make the compiler happy.  */
+  const char *errstring = NULL;
+  int result = 0;
+
+  /* Display information about what we are doing while debugging.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS))
+    _dl_debug_printf ("\
+checking for version `%s' in file %s [%lu] required by file %s [%lu]\n",
+		      string, DSO_FILENAME (map->l_name),
+		      map->l_ns, name, ns);
+
+  if (__glibc_unlikely (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL))
+    {
+      /* The file has no symbol versioning.  I.e., the dependent
+	 object was linked against another version of this file.  We
+	 only print a message if verbose output is requested.  */
+      if (verbose)
+	{
+	  /* XXX We cannot translate the messages.  */
+	  errstring = make_string ("\
+no version information available (required by ", name, ")");
+	  goto call_cerror;
+	}
+      return 0;
+    }
+
+  def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
+  assert (def_offset != 0);
+
+  def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
+  while (1)
+    {
+      /* Currently the version number of the definition entry is 1.
+	 Make sure all we see is this version.  */
+      if (__builtin_expect (def->vd_version, 1) != 1)
+	{
+	  char buf[20];
+	  buf[sizeof (buf) - 1] = '\0';
+	  /* XXX We cannot translate the message.  */
+	  errstring = make_string ("unsupported version ",
+				   _itoa (def->vd_version,
+					  &buf[sizeof (buf) - 1], 10, 0),
+				   " of Verdef record");
+	  result = 1;
+	  goto call_cerror;
+	}
+
+      /* Compare the hash values.  */
+      if (hash == def->vd_hash)
+	{
+	  ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);
+
+	  /* To be safe, compare the string as well.  */
+	  if (__builtin_expect (strcmp (string, strtab + aux->vda_name), 0)
+	      == 0)
+	    /* Bingo!  */
+	    return 0;
+	}
+
+      /* If no more definitions we failed to find what we want.  */
+      if (def->vd_next == 0)
+	break;
+
+      /* Next definition.  */
+      def = (ElfW(Verdef) *) ((char *) def + def->vd_next);
+    }
+
+  /* Symbol not found.  If it was a weak reference it is not fatal.  */
+  if (__glibc_likely (weak))
+    {
+      if (verbose)
+	{
+	  /* XXX We cannot translate the message.  */
+	  errstring = make_string ("weak version `", string,
+				   "' not found (required by ", name, ")");
+	  goto call_cerror;
+	}
+      return 0;
+    }
+
+  /* XXX We cannot translate the message.  */
+  errstring = make_string ("version `", string, "' not found (required by ",
+			   name, ")");
+  result = 1;
+ call_cerror:
+  _dl_signal_cerror (0, DSO_FILENAME (map->l_name),
+		     N_("version lookup error"), errstring);
+  return result;
+}
+
+
+int
+internal_function
+_dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
+{
+  int result = 0;
+  const char *strtab;
+  /* Pointer to section with needed versions.  */
+  ElfW(Dyn) *dyn;
+  /* Pointer to dynamic section with definitions.  */
+  ElfW(Dyn) *def;
+  /* We need to find out which is the highest version index used
+    in a dependecy.  */
+  unsigned int ndx_high = 0;
+  /* Initialize to make the compiler happy.  */
+  const char *errstring = NULL;
+  int errval = 0;
+
+  /* If we don't have a string table, we must be ok.  */
+  if (map->l_info[DT_STRTAB] == NULL)
+    return 0;
+  strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+  dyn = map->l_info[VERSYMIDX (DT_VERNEED)];
+  def = map->l_info[VERSYMIDX (DT_VERDEF)];
+
+  if (dyn != NULL)
+    {
+      /* This file requires special versions from its dependencies.  */
+      ElfW(Verneed) *ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
+
+      /* Currently the version number of the needed entry is 1.
+	 Make sure all we see is this version.  */
+      if (__builtin_expect (ent->vn_version, 1) != 1)
+	{
+	  char buf[20];
+	  buf[sizeof (buf) - 1] = '\0';
+	  /* XXX We cannot translate the message.  */
+	  errstring = make_string ("unsupported version ",
+				   _itoa (ent->vn_version,
+					  &buf[sizeof (buf) - 1], 10, 0),
+				   " of Verneed record\n");
+	call_error:
+	  _dl_signal_error (errval, DSO_FILENAME (map->l_name),
+			    NULL, errstring);
+	}
+
+      while (1)
+	{
+	  ElfW(Vernaux) *aux;
+	  struct link_map *needed = find_needed (strtab + ent->vn_file, map);
+
+	  /* If NEEDED is NULL this means a dependency was not found
+	     and no stub entry was created.  This should never happen.  */
+	  assert (needed != NULL);
+
+	  /* Make sure this is no stub we created because of a missing
+	     dependency.  */
+	  if (__builtin_expect (! trace_mode, 1)
+	      || ! __builtin_expect (needed->l_faked, 0))
+	    {
+	      /* NEEDED is the map for the file we need.  Now look for the
+		 dependency symbols.  */
+	      aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
+	      while (1)
+		{
+		  /* Match the symbol.  */
+		  result |= match_symbol (DSO_FILENAME (map->l_name),
+					  map->l_ns, aux->vna_hash,
+					  strtab + aux->vna_name,
+					  needed->l_real, verbose,
+					  aux->vna_flags & VER_FLG_WEAK);
+
+		  /* Compare the version index.  */
+		  if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
+		    ndx_high = aux->vna_other & 0x7fff;
+
+		  if (aux->vna_next == 0)
+		    /* No more symbols.  */
+		    break;
+
+		  /* Next symbol.  */
+		  aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
+		}
+	    }
+
+	  if (ent->vn_next == 0)
+	    /* No more dependencies.  */
+	    break;
+
+	  /* Next dependency.  */
+	  ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
+	}
+    }
+
+  /* We also must store the names of the defined versions.  Determine
+     the maximum index here as well.
+
+     XXX We could avoid the loop by just taking the number of definitions
+     as an upper bound of new indeces.  */
+  if (def != NULL)
+    {
+      ElfW(Verdef) *ent;
+      ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
+      while (1)
+	{
+	  if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high)
+	    ndx_high = ent->vd_ndx & 0x7fff;
+
+	  if (ent->vd_next == 0)
+	    /* No more definitions.  */
+	    break;
+
+	  ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
+	}
+    }
+
+  if (ndx_high > 0)
+    {
+      /* Now we are ready to build the array with the version names
+	 which can be indexed by the version index in the VERSYM
+	 section.  */
+      map->l_versions = (struct r_found_version *)
+	calloc (ndx_high + 1, sizeof (*map->l_versions));
+      if (__glibc_unlikely (map->l_versions == NULL))
+	{
+	  errstring = N_("cannot allocate version reference table");
+	  errval = ENOMEM;
+	  goto call_error;
+	}
+
+      /* Store the number of available symbols.  */
+      map->l_nversions = ndx_high + 1;
+
+      /* Compute the pointer to the version symbols.  */
+      map->l_versyms = (void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+
+      if (dyn != NULL)
+	{
+	  ElfW(Verneed) *ent;
+	  ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
+	  while (1)
+	    {
+	      ElfW(Vernaux) *aux;
+	      aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
+	      while (1)
+		{
+		  ElfW(Half) ndx = aux->vna_other & 0x7fff;
+		  /* In trace mode, dependencies may be missing.  */
+		  if (__glibc_likely (ndx < map->l_nversions))
+		    {
+		      map->l_versions[ndx].hash = aux->vna_hash;
+		      map->l_versions[ndx].hidden = aux->vna_other & 0x8000;
+		      map->l_versions[ndx].name = &strtab[aux->vna_name];
+		      map->l_versions[ndx].filename = &strtab[ent->vn_file];
+		    }
+
+		  if (aux->vna_next == 0)
+		    /* No more symbols.  */
+		    break;
+
+		  /* Advance to next symbol.  */
+		  aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
+		}
+
+	      if (ent->vn_next == 0)
+		/* No more dependencies.  */
+		break;
+
+	      /* Advance to next dependency.  */
+	      ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
+	    }
+	}
+
+      /* And insert the defined versions.  */
+      if (def != NULL)
+	{
+	  ElfW(Verdef) *ent;
+	  ent = (ElfW(Verdef)  *) (map->l_addr + def->d_un.d_ptr);
+	  while (1)
+	    {
+	      ElfW(Verdaux) *aux;
+	      aux = (ElfW(Verdaux) *) ((char *) ent + ent->vd_aux);
+
+	      if ((ent->vd_flags & VER_FLG_BASE) == 0)
+		{
+		  /* The name of the base version should not be
+		     available for matching a versioned symbol.  */
+		  ElfW(Half) ndx = ent->vd_ndx & 0x7fff;
+		  map->l_versions[ndx].hash = ent->vd_hash;
+		  map->l_versions[ndx].name = &strtab[aux->vda_name];
+		  map->l_versions[ndx].filename = NULL;
+		}
+
+	      if (ent->vd_next == 0)
+		/* No more definitions.  */
+		break;
+
+	      ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
+	    }
+	}
+    }
+
+  return result;
+}
+
+
+int
+internal_function
+_dl_check_all_versions (struct link_map *map, int verbose, int trace_mode)
+{
+  struct link_map *l;
+  int result = 0;
+
+  for (l = map; l != NULL; l = l->l_next)
+    result |= (! l->l_faked
+	       && _dl_check_map_versions (l, verbose, trace_mode));
+
+  return result;
+}
diff --git a/REORG.TODO/elf/dl-writev.h b/REORG.TODO/elf/dl-writev.h
new file mode 100644
index 0000000000..4db083bef6
--- /dev/null
+++ b/REORG.TODO/elf/dl-writev.h
@@ -0,0 +1,56 @@
+/* Message-writing for the dynamic linker.  Generic version.
+   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/uio.h>
+#include <ldsodefs.h>
+#include <libc-lock.h>
+
+/* This is used from only one place: dl-misc.c:_dl_debug_vdprintf.
+   Hence it's in a header with the expectation it will be inlined.
+
+   This is writev, but with a constraint added and others loosened:
+
+   1. Under RTLD_PRIVATE_ERRNO, it must not clobber the private errno
+      when another thread holds the dl_load_lock.
+   2. It is not obliged to detect and report errors at all.
+   3. It's not really obliged to deliver a single atomic write
+      (though it may be preferable).  */
+
+static inline void
+_dl_writev (int fd, const struct iovec *iov, size_t niov)
+{
+  /* Note that if __writev is an implementation that calls malloc,
+     this will cause linking problems building the dynamic linker.  */
+
+#if RTLD_PRIVATE_ERRNO
+  /* We have to take this lock just to be sure we don't clobber the private
+     errno when it's being used by another thread that cares about it.
+     Yet we must be sure not to try calling the lock functions before
+     the thread library is fully initialized.  */
+  if (__glibc_unlikely (_dl_starting_up))
+    __writev (fd, iov, niov);
+  else
+    {
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+      __writev (fd, iov, niov);
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+    }
+#else
+  __writev (fd, iov, niov);
+#endif
+}
diff --git a/REORG.TODO/elf/do-rel.h b/REORG.TODO/elf/do-rel.h
new file mode 100644
index 0000000000..70071e5c44
--- /dev/null
+++ b/REORG.TODO/elf/do-rel.h
@@ -0,0 +1,191 @@
+/* Do relocations for ELF dynamic linking.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file may be included twice, to define both
+   `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.  */
+
+#ifdef DO_RELA
+# define elf_dynamic_do_Rel		elf_dynamic_do_Rela
+# define Rel				Rela
+# define elf_machine_rel		elf_machine_rela
+# define elf_machine_rel_relative	elf_machine_rela_relative
+#endif
+
+#ifndef DO_ELF_MACHINE_REL_RELATIVE
+# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
+  elf_machine_rel_relative (l_addr, relative,				      \
+			    (void *) (l_addr + relative->r_offset))
+#endif
+
+/* Perform the relocations in MAP on the running program image as specified
+   by RELTAG, SZTAG.  If LAZY is nonzero, this is the first pass on PLT
+   relocations; they should be set up to call _dl_runtime_resolve, rather
+   than fully resolved now.  */
+
+auto inline void __attribute__ ((always_inline))
+elf_dynamic_do_Rel (struct link_map *map,
+		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
+		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
+		    int lazy, int skip_ifunc)
+{
+  const ElfW(Rel) *r = (const void *) reladdr;
+  const ElfW(Rel) *end = (const void *) (reladdr + relsize);
+  ElfW(Addr) l_addr = map->l_addr;
+# if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
+  const ElfW(Rel) *r2 = NULL;
+  const ElfW(Rel) *end2 = NULL;
+# endif
+
+#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
+  /* We never bind lazily during ld.so bootstrap.  Unfortunately gcc is
+     not clever enough to see through all the function calls to realize
+     that.  */
+  if (lazy)
+    {
+      /* Doing lazy PLT relocations; they need very little info.  */
+      for (; r < end; ++r)
+# ifdef ELF_MACHINE_IRELATIVE
+	if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
+	  {
+	    if (r2 == NULL)
+	      r2 = r;
+	    end2 = r;
+	  }
+	else
+# endif
+	  elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
+
+# ifdef ELF_MACHINE_IRELATIVE
+      if (r2 != NULL)
+	for (; r2 <= end2; ++r2)
+	  if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
+	    elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc);
+# endif
+    }
+  else
+#endif
+    {
+      const ElfW(Sym) *const symtab =
+	(const void *) D_PTR (map, l_info[DT_SYMTAB]);
+      const ElfW(Rel) *relative = r;
+      r += nrelative;
+
+#ifndef RTLD_BOOTSTRAP
+      /* This is defined in rtld.c, but nowhere in the static libc.a; make
+	 the reference weak so static programs can still link.  This
+	 declaration cannot be done when compiling rtld.c (i.e. #ifdef
+	 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
+	 _dl_rtld_map, which is incompatible with a weak decl in the same
+	 file.  */
+# ifndef SHARED
+      weak_extern (GL(dl_rtld_map));
+# endif
+      if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
+# if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE
+	/* Rela platforms get the offset from r_addend and this must
+	   be copied in the relocation address.  Therefore we can skip
+	   the relative relocations only if this is for rel
+	   relocations or rela relocations if they are computed as
+	   memory_loc += l_addr...  */
+	if (l_addr != 0)
+# else
+	/* ...or we know the object has been prelinked.  */
+	if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
+# endif
+#endif
+	  for (; relative < r; ++relative)
+	    DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
+
+#ifdef RTLD_BOOTSTRAP
+      /* The dynamic linker always uses versioning.  */
+      assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
+#else
+      if (map->l_info[VERSYMIDX (DT_VERSYM)])
+#endif
+	{
+	  const ElfW(Half) *const version =
+	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+
+	  for (; r < end; ++r)
+	    {
+#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
+	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
+		{
+		  if (r2 == NULL)
+		    r2 = r;
+		  end2 = r;
+		  continue;
+		}
+#endif
+
+	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
+	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
+			       &map->l_versions[ndx],
+			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	    }
+
+#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
+	  if (r2 != NULL)
+	    for (; r2 <= end2; ++r2)
+	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
+		{
+		  ElfW(Half) ndx
+		    = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
+		  elf_machine_rel (map, r2,
+				   &symtab[ELFW(R_SYM) (r2->r_info)],
+				   &map->l_versions[ndx],
+				   (void *) (l_addr + r2->r_offset),
+				   skip_ifunc);
+		}
+#endif
+	}
+#ifndef RTLD_BOOTSTRAP
+      else
+	{
+	  for (; r < end; ++r)
+# ifdef ELF_MACHINE_IRELATIVE
+	    if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
+	      {
+		if (r2 == NULL)
+		  r2 = r;
+		end2 = r;
+	      }
+	    else
+# endif
+	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
+			       (void *) (l_addr + r->r_offset), skip_ifunc);
+
+# ifdef ELF_MACHINE_IRELATIVE
+	  if (r2 != NULL)
+	    for (; r2 <= end2; ++r2)
+	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
+		elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
+				 NULL, (void *) (l_addr + r2->r_offset),
+				 skip_ifunc);
+# endif
+	}
+#endif
+    }
+}
+
+#undef elf_dynamic_do_Rel
+#undef Rel
+#undef elf_machine_rel
+#undef elf_machine_rel_relative
+#undef DO_ELF_MACHINE_REL_RELATIVE
+#undef DO_RELA
diff --git a/REORG.TODO/elf/dynamic-link.h b/REORG.TODO/elf/dynamic-link.h
new file mode 100644
index 0000000000..60f2d91151
--- /dev/null
+++ b/REORG.TODO/elf/dynamic-link.h
@@ -0,0 +1,203 @@
+/* Inline functions for dynamic linking.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This macro is used as a callback from elf_machine_rel{a,} when a
+   static TLS reloc is about to be performed.  Since (in dl-load.c) we
+   permit dynamic loading of objects that might use such relocs, we
+   have to check whether each use is actually doable.  If the object
+   whose TLS segment the reference resolves to was allocated space in
+   the static TLS block at startup, then it's ok.  Otherwise, we make
+   an attempt to allocate it in surplus space on the fly.  If that
+   can't be done, we fall back to the error that DF_STATIC_TLS is
+   intended to produce.  */
+#define HAVE_STATIC_TLS(map, sym_map)					\
+    (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET		\
+		       && ((sym_map)->l_tls_offset			\
+			   != FORCED_DYNAMIC_TLS_OFFSET), 1))
+
+#define CHECK_STATIC_TLS(map, sym_map)					\
+    do {								\
+      if (!HAVE_STATIC_TLS (map, sym_map))				\
+	_dl_allocate_static_tls (sym_map);				\
+    } while (0)
+
+#define TRY_STATIC_TLS(map, sym_map)					\
+    (__builtin_expect ((sym_map)->l_tls_offset				\
+		       != FORCED_DYNAMIC_TLS_OFFSET, 1)			\
+     && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1)	\
+	 || _dl_try_allocate_static_tls (sym_map) == 0))
+
+int internal_function attribute_hidden
+  _dl_try_allocate_static_tls (struct link_map *map);
+
+#include <elf.h>
+
+#ifdef RESOLVE_MAP
+/* We pass reloc_addr as a pointer to void, as opposed to a pointer to
+   ElfW(Addr), because not all architectures can assume that the
+   relocated address is properly aligned, whereas the compiler is
+   entitled to assume that a pointer to a type is properly aligned for
+   the type.  Even if we cast the pointer back to some other type with
+   less strict alignment requirements, the compiler might still
+   remember that the pointer was originally more aligned, thereby
+   optimizing away alignment tests or using word instructions for
+   copying memory, breaking the very code written to handle the
+   unaligned cases.  */
+# if ! ELF_MACHINE_NO_REL
+auto inline void __attribute__((always_inline))
+elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
+		 const ElfW(Sym) *sym, const struct r_found_version *version,
+		 void *const reloc_addr, int skip_ifunc);
+auto inline void __attribute__((always_inline))
+elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+			  void *const reloc_addr);
+# endif
+# if ! ELF_MACHINE_NO_RELA
+auto inline void __attribute__((always_inline))
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+		  const ElfW(Sym) *sym, const struct r_found_version *version,
+		  void *const reloc_addr, int skip_ifunc);
+auto inline void __attribute__((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+			   void *const reloc_addr);
+# endif
+# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
+auto inline void __attribute__((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+		      ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+		      int skip_ifunc);
+# else
+auto inline void __attribute__((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+		      ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+		      int skip_ifunc);
+# endif
+#endif
+
+#include <dl-machine.h>
+
+#include "get-dynamic-info.h"
+
+#ifdef RESOLVE_MAP
+
+# ifdef RTLD_BOOTSTRAP
+#  define ELF_DURING_STARTUP (1)
+# else
+#  define ELF_DURING_STARTUP (0)
+# endif
+
+/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
+   These functions are almost identical, so we use cpp magic to avoid
+   duplicating their code.  It cannot be done in a more general function
+   because we must be able to completely inline.  */
+
+/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
+   range.  Note that according to the ELF spec, this is completely legal!
+
+   We are guarenteed that we have one of three situations.  Either DT_JMPREL
+   comes immediately after DT_REL*, or there is overlap and DT_JMPREL
+   consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
+   are completely separate and there is a gap between them.  */
+
+# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
+  do {									      \
+    struct { ElfW(Addr) start, size;					      \
+	     __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; }  \
+      ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };			      \
+									      \
+    if ((map)->l_info[DT_##RELOC])					      \
+      {									      \
+	ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]);		      \
+	ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val;	      \
+	if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL)		      \
+	  ranges[0].nrelative						      \
+	    = map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val;	      \
+      }									      \
+    if ((map)->l_info[DT_PLTREL]					      \
+	&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
+      {									      \
+	ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]);		      \
+	ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;	      \
+									      \
+	if (ranges[0].start + ranges[0].size == (start + size))		      \
+	  ranges[0].size -= size;					      \
+	if (ELF_DURING_STARTUP						      \
+	    || (!(do_lazy)						      \
+		&& (ranges[0].start + ranges[0].size) == start))	      \
+	  {								      \
+	    /* Combine processing the sections.  */			      \
+	    ranges[0].size += size;					      \
+	  }								      \
+	else								      \
+	  {								      \
+	    ranges[1].start = start;					      \
+	    ranges[1].size = size;					      \
+	    ranges[1].lazy = (do_lazy);					      \
+	  }								      \
+      }									      \
+									      \
+    if (ELF_DURING_STARTUP)						      \
+      elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size,	      \
+			      ranges[0].nrelative, 0, skip_ifunc);	      \
+    else								      \
+      {									      \
+	int ranges_index;						      \
+	for (ranges_index = 0; ranges_index < 2; ++ranges_index)	      \
+	  elf_dynamic_do_##reloc ((map),				      \
+				  ranges[ranges_index].start,		      \
+				  ranges[ranges_index].size,		      \
+				  ranges[ranges_index].nrelative,	      \
+				  ranges[ranges_index].lazy,		      \
+				  skip_ifunc);				      \
+      }									      \
+  } while (0)
+
+# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
+#  define _ELF_CHECK_REL 0
+# else
+#  define _ELF_CHECK_REL 1
+# endif
+
+# if ! ELF_MACHINE_NO_REL
+#  include "do-rel.h"
+#  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
+  _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
+# else
+#  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do.  */
+# endif
+
+# if ! ELF_MACHINE_NO_RELA
+#  define DO_RELA
+#  include "do-rel.h"
+#  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
+  _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
+# else
+#  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do.  */
+# endif
+
+/* This can't just be an inline function because GCC is too dumb
+   to inline functions containing inlines themselves.  */
+# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \
+  do {									      \
+    int edr_lazy = elf_machine_runtime_setup ((map), (lazy),		      \
+					      (consider_profile));	      \
+    ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc);			      \
+    ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc);			      \
+  } while (0)
+
+#endif
diff --git a/REORG.TODO/elf/elf.h b/REORG.TODO/elf/elf.h
new file mode 100644
index 0000000000..fff893d433
--- /dev/null
+++ b/REORG.TODO/elf/elf.h
@@ -0,0 +1,3761 @@
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_H
+#define	_ELF_H 1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* Standard ELF types.  */
+
+#include <stdint.h>
+
+/* Type for a 16-bit quantity.  */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef uint32_t Elf32_Word;
+typedef	int32_t  Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef	int32_t  Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef uint64_t Elf32_Xword;
+typedef	int64_t  Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef	int64_t  Elf64_Sxword;
+
+/* Type of addresses.  */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets.  */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities.  */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information.  */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
+  Elf32_Half	e_type;			/* Object file type */
+  Elf32_Half	e_machine;		/* Architecture */
+  Elf32_Word	e_version;		/* Object file version */
+  Elf32_Addr	e_entry;		/* Entry point virtual address */
+  Elf32_Off	e_phoff;		/* Program header table file offset */
+  Elf32_Off	e_shoff;		/* Section header table file offset */
+  Elf32_Word	e_flags;		/* Processor-specific flags */
+  Elf32_Half	e_ehsize;		/* ELF header size in bytes */
+  Elf32_Half	e_phentsize;		/* Program header table entry size */
+  Elf32_Half	e_phnum;		/* Program header table entry count */
+  Elf32_Half	e_shentsize;		/* Section header table entry size */
+  Elf32_Half	e_shnum;		/* Section header table entry count */
+  Elf32_Half	e_shstrndx;		/* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
+  Elf64_Half	e_type;			/* Object file type */
+  Elf64_Half	e_machine;		/* Architecture */
+  Elf64_Word	e_version;		/* Object file version */
+  Elf64_Addr	e_entry;		/* Entry point virtual address */
+  Elf64_Off	e_phoff;		/* Program header table file offset */
+  Elf64_Off	e_shoff;		/* Section header table file offset */
+  Elf64_Word	e_flags;		/* Processor-specific flags */
+  Elf64_Half	e_ehsize;		/* ELF header size in bytes */
+  Elf64_Half	e_phentsize;		/* Program header table entry size */
+  Elf64_Half	e_phnum;		/* Program header table entry count */
+  Elf64_Half	e_shentsize;		/* Section header table entry size */
+  Elf64_Half	e_shnum;		/* Section header table entry count */
+  Elf64_Half	e_shstrndx;		/* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array.  The EI_* macros are indices into the
+   array.  The macros under each EI_* macro are the values the byte
+   may have.  */
+
+#define EI_MAG0		0		/* File identification byte 0 index */
+#define ELFMAG0		0x7f		/* Magic number byte 0 */
+
+#define EI_MAG1		1		/* File identification byte 1 index */
+#define ELFMAG1		'E'		/* Magic number byte 1 */
+
+#define EI_MAG2		2		/* File identification byte 2 index */
+#define ELFMAG2		'L'		/* Magic number byte 2 */
+
+#define EI_MAG3		3		/* File identification byte 3 index */
+#define ELFMAG3		'F'		/* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word.  */
+#define	ELFMAG		"\177ELF"
+#define	SELFMAG		4
+
+#define EI_CLASS	4		/* File class byte index */
+#define ELFCLASSNONE	0		/* Invalid class */
+#define ELFCLASS32	1		/* 32-bit objects */
+#define ELFCLASS64	2		/* 64-bit objects */
+#define ELFCLASSNUM	3
+
+#define EI_DATA		5		/* Data encoding byte index */
+#define ELFDATANONE	0		/* Invalid data encoding */
+#define ELFDATA2LSB	1		/* 2's complement, little endian */
+#define ELFDATA2MSB	2		/* 2's complement, big endian */
+#define ELFDATANUM	3
+
+#define EI_VERSION	6		/* File version byte index */
+					/* Value must be EV_CURRENT */
+
+#define EI_OSABI	7		/* OS ABI identification */
+#define ELFOSABI_NONE		0	/* UNIX System V ABI */
+#define ELFOSABI_SYSV		0	/* Alias.  */
+#define ELFOSABI_HPUX		1	/* HP-UX */
+#define ELFOSABI_NETBSD		2	/* NetBSD.  */
+#define ELFOSABI_GNU		3	/* Object uses GNU ELF extensions.  */
+#define ELFOSABI_LINUX		ELFOSABI_GNU /* Compatibility alias.  */
+#define ELFOSABI_SOLARIS	6	/* Sun Solaris.  */
+#define ELFOSABI_AIX		7	/* IBM AIX.  */
+#define ELFOSABI_IRIX		8	/* SGI Irix.  */
+#define ELFOSABI_FREEBSD	9	/* FreeBSD.  */
+#define ELFOSABI_TRU64		10	/* Compaq TRU64 UNIX.  */
+#define ELFOSABI_MODESTO	11	/* Novell Modesto.  */
+#define ELFOSABI_OPENBSD	12	/* OpenBSD.  */
+#define ELFOSABI_ARM_AEABI	64	/* ARM EABI */
+#define ELFOSABI_ARM		97	/* ARM */
+#define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */
+
+#define EI_ABIVERSION	8		/* ABI version */
+
+#define EI_PAD		9		/* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type).  */
+
+#define ET_NONE		0		/* No file type */
+#define ET_REL		1		/* Relocatable file */
+#define ET_EXEC		2		/* Executable file */
+#define ET_DYN		3		/* Shared object file */
+#define ET_CORE		4		/* Core file */
+#define	ET_NUM		5		/* Number of defined types */
+#define ET_LOOS		0xfe00		/* OS-specific range start */
+#define ET_HIOS		0xfeff		/* OS-specific range end */
+#define ET_LOPROC	0xff00		/* Processor-specific range start */
+#define ET_HIPROC	0xffff		/* Processor-specific range end */
+
+/* Legal values for e_machine (architecture).  */
+
+#define EM_NONE		 0	/* No machine */
+#define EM_M32		 1	/* AT&T WE 32100 */
+#define EM_SPARC	 2	/* SUN SPARC */
+#define EM_386		 3	/* Intel 80386 */
+#define EM_68K		 4	/* Motorola m68k family */
+#define EM_88K		 5	/* Motorola m88k family */
+#define EM_IAMCU	 6	/* Intel MCU */
+#define EM_860		 7	/* Intel 80860 */
+#define EM_MIPS		 8	/* MIPS R3000 big-endian */
+#define EM_S370		 9	/* IBM System/370 */
+#define EM_MIPS_RS3_LE	10	/* MIPS R3000 little-endian */
+				/* reserved 11-14 */
+#define EM_PARISC	15	/* HPPA */
+				/* reserved 16 */
+#define EM_VPP500	17	/* Fujitsu VPP500 */
+#define EM_SPARC32PLUS	18	/* Sun's "v8plus" */
+#define EM_960		19	/* Intel 80960 */
+#define EM_PPC		20	/* PowerPC */
+#define EM_PPC64	21	/* PowerPC 64-bit */
+#define EM_S390		22	/* IBM S390 */
+#define EM_SPU		23	/* IBM SPU/SPC */
+				/* reserved 24-35 */
+#define EM_V800		36	/* NEC V800 series */
+#define EM_FR20		37	/* Fujitsu FR20 */
+#define EM_RH32		38	/* TRW RH-32 */
+#define EM_RCE		39	/* Motorola RCE */
+#define EM_ARM		40	/* ARM */
+#define EM_FAKE_ALPHA	41	/* Digital Alpha */
+#define EM_SH		42	/* Hitachi SH */
+#define EM_SPARCV9	43	/* SPARC v9 64-bit */
+#define EM_TRICORE	44	/* Siemens Tricore */
+#define EM_ARC		45	/* Argonaut RISC Core */
+#define EM_H8_300	46	/* Hitachi H8/300 */
+#define EM_H8_300H	47	/* Hitachi H8/300H */
+#define EM_H8S		48	/* Hitachi H8S */
+#define EM_H8_500	49	/* Hitachi H8/500 */
+#define EM_IA_64	50	/* Intel Merced */
+#define EM_MIPS_X	51	/* Stanford MIPS-X */
+#define EM_COLDFIRE	52	/* Motorola Coldfire */
+#define EM_68HC12	53	/* Motorola M68HC12 */
+#define EM_MMA		54	/* Fujitsu MMA Multimedia Accelerator */
+#define EM_PCP		55	/* Siemens PCP */
+#define EM_NCPU		56	/* Sony nCPU embeeded RISC */
+#define EM_NDR1		57	/* Denso NDR1 microprocessor */
+#define EM_STARCORE	58	/* Motorola Start*Core processor */
+#define EM_ME16		59	/* Toyota ME16 processor */
+#define EM_ST100	60	/* STMicroelectronic ST100 processor */
+#define EM_TINYJ	61	/* Advanced Logic Corp. Tinyj emb.fam */
+#define EM_X86_64	62	/* AMD x86-64 architecture */
+#define EM_PDSP		63	/* Sony DSP Processor */
+#define EM_PDP10	64	/* Digital PDP-10 */
+#define EM_PDP11	65	/* Digital PDP-11 */
+#define EM_FX66		66	/* Siemens FX66 microcontroller */
+#define EM_ST9PLUS	67	/* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7		68	/* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16	69	/* Motorola MC68HC16 microcontroller */
+#define EM_68HC11	70	/* Motorola MC68HC11 microcontroller */
+#define EM_68HC08	71	/* Motorola MC68HC08 microcontroller */
+#define EM_68HC05	72	/* Motorola MC68HC05 microcontroller */
+#define EM_SVX		73	/* Silicon Graphics SVx */
+#define EM_ST19		74	/* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX		75	/* Digital VAX */
+#define EM_CRIS		76	/* Axis Communications 32-bit emb.proc */
+#define EM_JAVELIN	77	/* Infineon Technologies 32-bit emb.proc */
+#define EM_FIREPATH	78	/* Element 14 64-bit DSP Processor */
+#define EM_ZSP		79	/* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX		80	/* Donald Knuth's educational 64-bit proc */
+#define EM_HUANY	81	/* Harvard University machine-independent object files */
+#define EM_PRISM	82	/* SiTera Prism */
+#define EM_AVR		83	/* Atmel AVR 8-bit microcontroller */
+#define EM_FR30		84	/* Fujitsu FR30 */
+#define EM_D10V		85	/* Mitsubishi D10V */
+#define EM_D30V		86	/* Mitsubishi D30V */
+#define EM_V850		87	/* NEC v850 */
+#define EM_M32R		88	/* Mitsubishi M32R */
+#define EM_MN10300	89	/* Matsushita MN10300 */
+#define EM_MN10200	90	/* Matsushita MN10200 */
+#define EM_PJ		91	/* picoJava */
+#define EM_OPENRISC	92	/* OpenRISC 32-bit embedded processor */
+#define EM_ARC_COMPACT	93	/* ARC International ARCompact */
+#define EM_XTENSA	94	/* Tensilica Xtensa Architecture */
+#define EM_VIDEOCORE	95	/* Alphamosaic VideoCore */
+#define EM_TMM_GPP	96	/* Thompson Multimedia General Purpose Proc */
+#define EM_NS32K	97	/* National Semi. 32000 */
+#define EM_TPC		98	/* Tenor Network TPC */
+#define EM_SNP1K	99	/* Trebia SNP 1000 */
+#define EM_ST200	100	/* STMicroelectronics ST200 */
+#define EM_IP2K		101	/* Ubicom IP2xxx */
+#define EM_MAX		102	/* MAX processor */
+#define EM_CR		103	/* National Semi. CompactRISC */
+#define EM_F2MC16	104	/* Fujitsu F2MC16 */
+#define EM_MSP430	105	/* Texas Instruments msp430 */
+#define EM_BLACKFIN	106	/* Analog Devices Blackfin DSP */
+#define EM_SE_C33	107	/* Seiko Epson S1C33 family */
+#define EM_SEP		108	/* Sharp embedded microprocessor */
+#define EM_ARCA		109	/* Arca RISC */
+#define EM_UNICORE	110	/* PKU-Unity & MPRC Peking Uni. mc series */
+#define EM_EXCESS	111	/* eXcess configurable cpu */
+#define EM_DXP		112	/* Icera Semi. Deep Execution Processor */
+#define EM_ALTERA_NIOS2 113	/* Altera Nios II */
+#define EM_CRX		114	/* National Semi. CompactRISC CRX */
+#define EM_XGATE	115	/* Motorola XGATE */
+#define EM_C166		116	/* Infineon C16x/XC16x */
+#define EM_M16C		117	/* Renesas M16C */
+#define EM_DSPIC30F	118	/* Microchip Technology dsPIC30F */
+#define EM_CE		119	/* Freescale Communication Engine RISC */
+#define EM_M32C		120	/* Renesas M32C */
+				/* reserved 121-130 */
+#define EM_TSK3000	131	/* Altium TSK3000 */
+#define EM_RS08		132	/* Freescale RS08 */
+#define EM_SHARC	133	/* Analog Devices SHARC family */
+#define EM_ECOG2	134	/* Cyan Technology eCOG2 */
+#define EM_SCORE7	135	/* Sunplus S+core7 RISC */
+#define EM_DSP24	136	/* New Japan Radio (NJR) 24-bit DSP */
+#define EM_VIDEOCORE3	137	/* Broadcom VideoCore III */
+#define EM_LATTICEMICO32 138	/* RISC for Lattice FPGA */
+#define EM_SE_C17	139	/* Seiko Epson C17 */
+#define EM_TI_C6000	140	/* Texas Instruments TMS320C6000 DSP */
+#define EM_TI_C2000	141	/* Texas Instruments TMS320C2000 DSP */
+#define EM_TI_C5500	142	/* Texas Instruments TMS320C55x DSP */
+#define EM_TI_ARP32	143	/* Texas Instruments App. Specific RISC */
+#define EM_TI_PRU	144	/* Texas Instruments Prog. Realtime Unit */
+				/* reserved 145-159 */
+#define EM_MMDSP_PLUS	160	/* STMicroelectronics 64bit VLIW DSP */
+#define EM_CYPRESS_M8C	161	/* Cypress M8C */
+#define EM_R32C		162	/* Renesas R32C */
+#define EM_TRIMEDIA	163	/* NXP Semi. TriMedia */
+#define EM_QDSP6	164	/* QUALCOMM DSP6 */
+#define EM_8051		165	/* Intel 8051 and variants */
+#define EM_STXP7X	166	/* STMicroelectronics STxP7x */
+#define EM_NDS32	167	/* Andes Tech. compact code emb. RISC */
+#define EM_ECOG1X	168	/* Cyan Technology eCOG1X */
+#define EM_MAXQ30	169	/* Dallas Semi. MAXQ30 mc */
+#define EM_XIMO16	170	/* New Japan Radio (NJR) 16-bit DSP */
+#define EM_MANIK	171	/* M2000 Reconfigurable RISC */
+#define EM_CRAYNV2	172	/* Cray NV2 vector architecture */
+#define EM_RX		173	/* Renesas RX */
+#define EM_METAG	174	/* Imagination Tech. META */
+#define EM_MCST_ELBRUS	175	/* MCST Elbrus */
+#define EM_ECOG16	176	/* Cyan Technology eCOG16 */
+#define EM_CR16		177	/* National Semi. CompactRISC CR16 */
+#define EM_ETPU		178	/* Freescale Extended Time Processing Unit */
+#define EM_SLE9X	179	/* Infineon Tech. SLE9X */
+#define EM_L10M		180	/* Intel L10M */
+#define EM_K10M		181	/* Intel K10M */
+				/* reserved 182 */
+#define EM_AARCH64	183	/* ARM AARCH64 */
+				/* reserved 184 */
+#define EM_AVR32	185	/* Amtel 32-bit microprocessor */
+#define EM_STM8		186	/* STMicroelectronics STM8 */
+#define EM_TILE64	187	/* Tileta TILE64 */
+#define EM_TILEPRO	188	/* Tilera TILEPro */
+#define EM_MICROBLAZE	189	/* Xilinx MicroBlaze */
+#define EM_CUDA		190	/* NVIDIA CUDA */
+#define EM_TILEGX	191	/* Tilera TILE-Gx */
+#define EM_CLOUDSHIELD	192	/* CloudShield */
+#define EM_COREA_1ST	193	/* KIPO-KAIST Core-A 1st gen. */
+#define EM_COREA_2ND	194	/* KIPO-KAIST Core-A 2nd gen. */
+#define EM_ARC_COMPACT2	195	/* Synopsys ARCompact V2 */
+#define EM_OPEN8	196	/* Open8 RISC */
+#define EM_RL78		197	/* Renesas RL78 */
+#define EM_VIDEOCORE5	198	/* Broadcom VideoCore V */
+#define EM_78KOR	199	/* Renesas 78KOR */
+#define EM_56800EX	200	/* Freescale 56800EX DSC */
+#define EM_BA1		201	/* Beyond BA1 */
+#define EM_BA2		202	/* Beyond BA2 */
+#define EM_XCORE	203	/* XMOS xCORE */
+#define EM_MCHP_PIC	204	/* Microchip 8-bit PIC(r) */
+				/* reserved 205-209 */
+#define EM_KM32		210	/* KM211 KM32 */
+#define EM_KMX32	211	/* KM211 KMX32 */
+#define EM_EMX16	212	/* KM211 KMX16 */
+#define EM_EMX8		213	/* KM211 KMX8 */
+#define EM_KVARC	214	/* KM211 KVARC */
+#define EM_CDP		215	/* Paneve CDP */
+#define EM_COGE		216	/* Cognitive Smart Memory Processor */
+#define EM_COOL		217	/* Bluechip CoolEngine */
+#define EM_NORC		218	/* Nanoradio Optimized RISC */
+#define EM_CSR_KALIMBA	219	/* CSR Kalimba */
+#define EM_Z80		220	/* Zilog Z80 */
+#define EM_VISIUM	221	/* Controls and Data Services VISIUMcore */
+#define EM_FT32		222	/* FTDI Chip FT32 */
+#define EM_MOXIE	223	/* Moxie processor */
+#define EM_AMDGPU	224	/* AMD GPU */
+				/* reserved 225-242 */
+#define EM_RISCV	243	/* RISC-V */
+
+#define EM_BPF		247	/* Linux BPF -- in-kernel virtual machine */
+
+#define EM_NUM		248
+
+/* Old spellings/synonyms.  */
+
+#define EM_ARC_A5	EM_ARC_COMPACT
+
+/* If it is necessary to assign new unofficial EM_* values, please
+   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+   chances of collision with official or non-GNU unofficial values.  */
+
+#define EM_ALPHA	0x9026
+
+/* Legal values for e_version (version).  */
+
+#define EV_NONE		0		/* Invalid ELF version */
+#define EV_CURRENT	1		/* Current version */
+#define EV_NUM		2
+
+/* Section header.  */
+
+typedef struct
+{
+  Elf32_Word	sh_name;		/* Section name (string tbl index) */
+  Elf32_Word	sh_type;		/* Section type */
+  Elf32_Word	sh_flags;		/* Section flags */
+  Elf32_Addr	sh_addr;		/* Section virtual addr at execution */
+  Elf32_Off	sh_offset;		/* Section file offset */
+  Elf32_Word	sh_size;		/* Section size in bytes */
+  Elf32_Word	sh_link;		/* Link to another section */
+  Elf32_Word	sh_info;		/* Additional section information */
+  Elf32_Word	sh_addralign;		/* Section alignment */
+  Elf32_Word	sh_entsize;		/* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word	sh_name;		/* Section name (string tbl index) */
+  Elf64_Word	sh_type;		/* Section type */
+  Elf64_Xword	sh_flags;		/* Section flags */
+  Elf64_Addr	sh_addr;		/* Section virtual addr at execution */
+  Elf64_Off	sh_offset;		/* Section file offset */
+  Elf64_Xword	sh_size;		/* Section size in bytes */
+  Elf64_Word	sh_link;		/* Link to another section */
+  Elf64_Word	sh_info;		/* Additional section information */
+  Elf64_Xword	sh_addralign;		/* Section alignment */
+  Elf64_Xword	sh_entsize;		/* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices.  */
+
+#define SHN_UNDEF	0		/* Undefined section */
+#define SHN_LORESERVE	0xff00		/* Start of reserved indices */
+#define SHN_LOPROC	0xff00		/* Start of processor-specific */
+#define SHN_BEFORE	0xff00		/* Order section before all others
+					   (Solaris).  */
+#define SHN_AFTER	0xff01		/* Order section after all others
+					   (Solaris).  */
+#define SHN_HIPROC	0xff1f		/* End of processor-specific */
+#define SHN_LOOS	0xff20		/* Start of OS-specific */
+#define SHN_HIOS	0xff3f		/* End of OS-specific */
+#define SHN_ABS		0xfff1		/* Associated symbol is absolute */
+#define SHN_COMMON	0xfff2		/* Associated symbol is common */
+#define SHN_XINDEX	0xffff		/* Index is in extra table.  */
+#define SHN_HIRESERVE	0xffff		/* End of reserved indices */
+
+/* Legal values for sh_type (section type).  */
+
+#define SHT_NULL	  0		/* Section header table entry unused */
+#define SHT_PROGBITS	  1		/* Program data */
+#define SHT_SYMTAB	  2		/* Symbol table */
+#define SHT_STRTAB	  3		/* String table */
+#define SHT_RELA	  4		/* Relocation entries with addends */
+#define SHT_HASH	  5		/* Symbol hash table */
+#define SHT_DYNAMIC	  6		/* Dynamic linking information */
+#define SHT_NOTE	  7		/* Notes */
+#define SHT_NOBITS	  8		/* Program space with no data (bss) */
+#define SHT_REL		  9		/* Relocation entries, no addends */
+#define SHT_SHLIB	  10		/* Reserved */
+#define SHT_DYNSYM	  11		/* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY	  14		/* Array of constructors */
+#define SHT_FINI_ARRAY	  15		/* Array of destructors */
+#define SHT_PREINIT_ARRAY 16		/* Array of pre-constructors */
+#define SHT_GROUP	  17		/* Section group */
+#define SHT_SYMTAB_SHNDX  18		/* Extended section indeces */
+#define	SHT_NUM		  19		/* Number of defined types.  */
+#define SHT_LOOS	  0x60000000	/* Start OS-specific.  */
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5	/* Object attributes.  */
+#define SHT_GNU_HASH	  0x6ffffff6	/* GNU-style hash table.  */
+#define SHT_GNU_LIBLIST	  0x6ffffff7	/* Prelink library list */
+#define SHT_CHECKSUM	  0x6ffffff8	/* Checksum for DSO content.  */
+#define SHT_LOSUNW	  0x6ffffffa	/* Sun-specific low bound.  */
+#define SHT_SUNW_move	  0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef	  0x6ffffffd	/* Version definition section.  */
+#define SHT_GNU_verneed	  0x6ffffffe	/* Version needs section.  */
+#define SHT_GNU_versym	  0x6fffffff	/* Version symbol table.  */
+#define SHT_HISUNW	  0x6fffffff	/* Sun-specific high bound.  */
+#define SHT_HIOS	  0x6fffffff	/* End OS-specific type */
+#define SHT_LOPROC	  0x70000000	/* Start of processor-specific */
+#define SHT_HIPROC	  0x7fffffff	/* End of processor-specific */
+#define SHT_LOUSER	  0x80000000	/* Start of application-specific */
+#define SHT_HIUSER	  0x8fffffff	/* End of application-specific */
+
+/* Legal values for sh_flags (section flags).  */
+
+#define SHF_WRITE	     (1 << 0)	/* Writable */
+#define SHF_ALLOC	     (1 << 1)	/* Occupies memory during execution */
+#define SHF_EXECINSTR	     (1 << 2)	/* Executable */
+#define SHF_MERGE	     (1 << 4)	/* Might be merged */
+#define SHF_STRINGS	     (1 << 5)	/* Contains nul-terminated strings */
+#define SHF_INFO_LINK	     (1 << 6)	/* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER	     (1 << 7)	/* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8)	/* Non-standard OS specific handling
+					   required */
+#define SHF_GROUP	     (1 << 9)	/* Section is member of a group.  */
+#define SHF_TLS		     (1 << 10)	/* Section hold thread-local data.  */
+#define SHF_COMPRESSED	     (1 << 11)	/* Section with compressed data. */
+#define SHF_MASKOS	     0x0ff00000	/* OS-specific.  */
+#define SHF_MASKPROC	     0xf0000000	/* Processor-specific */
+#define SHF_ORDERED	     (1 << 30)	/* Special ordering requirement
+					   (Solaris).  */
+#define SHF_EXCLUDE	     (1U << 31)	/* Section is excluded unless
+					   referenced or allocated (Solaris).*/
+
+/* Section compression header.  Used when SHF_COMPRESSED is set.  */
+
+typedef struct
+{
+  Elf32_Word	ch_type;	/* Compression format.  */
+  Elf32_Word	ch_size;	/* Uncompressed data size.  */
+  Elf32_Word	ch_addralign;	/* Uncompressed data alignment.  */
+} Elf32_Chdr;
+
+typedef struct
+{
+  Elf64_Word	ch_type;	/* Compression format.  */
+  Elf64_Word	ch_reserved;
+  Elf64_Xword	ch_size;	/* Uncompressed data size.  */
+  Elf64_Xword	ch_addralign;	/* Uncompressed data alignment.  */
+} Elf64_Chdr;
+
+/* Legal values for ch_type (compression algorithm).  */
+#define ELFCOMPRESS_ZLIB	1	   /* ZLIB/DEFLATE algorithm.  */
+#define ELFCOMPRESS_LOOS	0x60000000 /* Start of OS-specific.  */
+#define ELFCOMPRESS_HIOS	0x6fffffff /* End of OS-specific.  */
+#define ELFCOMPRESS_LOPROC	0x70000000 /* Start of processor-specific.  */
+#define ELFCOMPRESS_HIPROC	0x7fffffff /* End of processor-specific.  */
+
+/* Section group handling.  */
+#define GRP_COMDAT	0x1		/* Mark group as COMDAT.  */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word	st_name;		/* Symbol name (string tbl index) */
+  Elf32_Addr	st_value;		/* Symbol value */
+  Elf32_Word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char	st_other;		/* Symbol visibility */
+  Elf32_Section	st_shndx;		/* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word	st_name;		/* Symbol name (string tbl index) */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char st_other;		/* Symbol visibility */
+  Elf64_Section	st_shndx;		/* Section index */
+  Elf64_Addr	st_value;		/* Symbol value */
+  Elf64_Xword	st_size;		/* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+
+typedef struct
+{
+  Elf32_Half si_boundto;		/* Direct bindings, symbol bound to */
+  Elf32_Half si_flags;			/* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;		/* Direct bindings, symbol bound to */
+  Elf64_Half si_flags;			/* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto.  */
+#define SYMINFO_BT_SELF		0xffff	/* Symbol bound to self */
+#define SYMINFO_BT_PARENT	0xfffe	/* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE	0xff00	/* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags.  */
+#define SYMINFO_FLG_DIRECT	0x0001	/* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU	0x0002	/* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY	0x0004	/* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD	0x0008	/* Symbol bound to object to be lazy
+					   loaded */
+/* Syminfo version values.  */
+#define SYMINFO_NONE		0
+#define SYMINFO_CURRENT		1
+#define SYMINFO_NUM		2
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define ELF32_ST_BIND(val)		(((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)		((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)	(((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
+#define ELF64_ST_BIND(val)		ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)		ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)	ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+
+#define STB_LOCAL	0		/* Local symbol */
+#define STB_GLOBAL	1		/* Global symbol */
+#define STB_WEAK	2		/* Weak symbol */
+#define	STB_NUM		3		/* Number of defined types.  */
+#define STB_LOOS	10		/* Start of OS-specific */
+#define STB_GNU_UNIQUE	10		/* Unique symbol.  */
+#define STB_HIOS	12		/* End of OS-specific */
+#define STB_LOPROC	13		/* Start of processor-specific */
+#define STB_HIPROC	15		/* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_NOTYPE	0		/* Symbol type is unspecified */
+#define STT_OBJECT	1		/* Symbol is a data object */
+#define STT_FUNC	2		/* Symbol is a code object */
+#define STT_SECTION	3		/* Symbol associated with a section */
+#define STT_FILE	4		/* Symbol's name is file name */
+#define STT_COMMON	5		/* Symbol is a common data object */
+#define STT_TLS		6		/* Symbol is thread-local data object*/
+#define	STT_NUM		7		/* Number of defined types.  */
+#define STT_LOOS	10		/* Start of OS-specific */
+#define STT_GNU_IFUNC	10		/* Symbol is indirect code object */
+#define STT_HIOS	12		/* End of OS-specific */
+#define STT_LOPROC	13		/* Start of processor-specific */
+#define STT_HIPROC	15		/* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+   of a symbol hash table section.  This special index value indicates
+   the end of a chain, meaning no further symbols are found in that bucket.  */
+
+#define STN_UNDEF	0		/* End of a chain.  */
+
+
+/* How to extract and insert information held in the st_other field.  */
+
+#define ELF32_ST_VISIBILITY(o)	((o) & 0x03)
+
+/* For ELF64 the definitions are the same.  */
+#define ELF64_ST_VISIBILITY(o)	ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field.  */
+#define STV_DEFAULT	0		/* Default symbol visibility rules */
+#define STV_INTERNAL	1		/* Processor specific hidden class */
+#define STV_HIDDEN	2		/* Sym unavailable in other modules */
+#define STV_PROTECTED	3		/* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+
+typedef struct
+{
+  Elf32_Addr	r_offset;		/* Address */
+  Elf32_Word	r_info;			/* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+   Elf64_Rela structures, so we'll leave them out until Novell (or
+   whoever) gets their act together.  */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
+
+typedef struct
+{
+  Elf64_Addr	r_offset;		/* Address */
+  Elf64_Xword	r_info;			/* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+
+typedef struct
+{
+  Elf32_Addr	r_offset;		/* Address */
+  Elf32_Word	r_info;			/* Relocation type and symbol index */
+  Elf32_Sword	r_addend;		/* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr	r_offset;		/* Address */
+  Elf64_Xword	r_info;			/* Relocation type and symbol index */
+  Elf64_Sxword	r_addend;		/* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define ELF32_R_SYM(val)		((val) >> 8)
+#define ELF32_R_TYPE(val)		((val) & 0xff)
+#define ELF32_R_INFO(sym, type)		(((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)			((i) >> 32)
+#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)		((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header.  */
+
+typedef struct
+{
+  Elf32_Word	p_type;			/* Segment type */
+  Elf32_Off	p_offset;		/* Segment file offset */
+  Elf32_Addr	p_vaddr;		/* Segment virtual address */
+  Elf32_Addr	p_paddr;		/* Segment physical address */
+  Elf32_Word	p_filesz;		/* Segment size in file */
+  Elf32_Word	p_memsz;		/* Segment size in memory */
+  Elf32_Word	p_flags;		/* Segment flags */
+  Elf32_Word	p_align;		/* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word	p_type;			/* Segment type */
+  Elf64_Word	p_flags;		/* Segment flags */
+  Elf64_Off	p_offset;		/* Segment file offset */
+  Elf64_Addr	p_vaddr;		/* Segment virtual address */
+  Elf64_Addr	p_paddr;		/* Segment physical address */
+  Elf64_Xword	p_filesz;		/* Segment size in file */
+  Elf64_Xword	p_memsz;		/* Segment size in memory */
+  Elf64_Xword	p_align;		/* Segment alignment */
+} Elf64_Phdr;
+
+/* Special value for e_phnum.  This indicates that the real number of
+   program headers is too large to fit into e_phnum.  Instead the real
+   value is in the field sh_info of section 0.  */
+
+#define PN_XNUM		0xffff
+
+/* Legal values for p_type (segment type).  */
+
+#define	PT_NULL		0		/* Program header table entry unused */
+#define PT_LOAD		1		/* Loadable program segment */
+#define PT_DYNAMIC	2		/* Dynamic linking information */
+#define PT_INTERP	3		/* Program interpreter */
+#define PT_NOTE		4		/* Auxiliary information */
+#define PT_SHLIB	5		/* Reserved */
+#define PT_PHDR		6		/* Entry for header table itself */
+#define PT_TLS		7		/* Thread-local storage segment */
+#define	PT_NUM		8		/* Number of defined types */
+#define PT_LOOS		0x60000000	/* Start of OS-specific */
+#define PT_GNU_EH_FRAME	0x6474e550	/* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK	0x6474e551	/* Indicates stack executability */
+#define PT_GNU_RELRO	0x6474e552	/* Read-only after relocation */
+#define PT_LOSUNW	0x6ffffffa
+#define PT_SUNWBSS	0x6ffffffa	/* Sun Specific segment */
+#define PT_SUNWSTACK	0x6ffffffb	/* Stack segment */
+#define PT_HISUNW	0x6fffffff
+#define PT_HIOS		0x6fffffff	/* End of OS-specific */
+#define PT_LOPROC	0x70000000	/* Start of processor-specific */
+#define PT_HIPROC	0x7fffffff	/* End of processor-specific */
+
+/* Legal values for p_flags (segment flags).  */
+
+#define PF_X		(1 << 0)	/* Segment is executable */
+#define PF_W		(1 << 1)	/* Segment is writable */
+#define PF_R		(1 << 2)	/* Segment is readable */
+#define PF_MASKOS	0x0ff00000	/* OS-specific */
+#define PF_MASKPROC	0xf0000000	/* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
+#define NT_FPREGSET	2		/* Contains copy of fpregset struct */
+#define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+#define NT_PRXREG	4		/* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT	4		/* Contains copy of task structure */
+#define NT_PLATFORM	5		/* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV		6		/* Contains copy of auxv array */
+#define NT_GWINDOWS	7		/* Contains copy of gwindows struct */
+#define NT_ASRS		8		/* Contains copy of asrset struct */
+#define NT_PSTATUS	10		/* Contains copy of pstatus struct */
+#define NT_PSINFO	13		/* Contains copy of psinfo struct */
+#define NT_PRCRED	14		/* Contains copy of prcred struct */
+#define NT_UTSNAME	15		/* Contains copy of utsname struct */
+#define NT_LWPSTATUS	16		/* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO	17		/* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG	20		/* Contains copy of fprxregset struct */
+#define NT_SIGINFO	0x53494749	/* Contains copy of siginfo_t,
+					   size might increase */
+#define NT_FILE		0x46494c45	/* Contains information about mapped
+					   files */
+#define NT_PRXFPREG	0x46e62b7f	/* Contains copy of user_fxsr_struct */
+#define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
+#define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
+#define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
+#define NT_S390_HIGH_GPRS	0x300	/* s390 upper register halves */
+#define NT_S390_TIMER	0x301		/* s390 timer register */
+#define NT_S390_TODCMP	0x302		/* s390 TOD clock comparator register */
+#define NT_S390_TODPREG	0x303		/* s390 TOD programmable register */
+#define NT_S390_CTRS	0x304		/* s390 control registers */
+#define NT_S390_PREFIX	0x305		/* s390 prefix register */
+#define NT_S390_LAST_BREAK	0x306	/* s390 breaking event address */
+#define NT_S390_SYSTEM_CALL	0x307	/* s390 system call restart data */
+#define NT_S390_TDB	0x308		/* s390 transaction diagnostic block */
+#define NT_ARM_VFP	0x400		/* ARM VFP/NEON registers */
+#define NT_ARM_TLS	0x401		/* ARM TLS register */
+#define NT_ARM_HW_BREAK	0x402		/* ARM hardware breakpoint registers */
+#define NT_ARM_HW_WATCH	0x403		/* ARM hardware watchpoint registers */
+#define NT_ARM_SYSTEM_CALL	0x404	/* ARM system call number */
+
+/* Legal values for the note segment descriptor types for object files.  */
+
+#define NT_VERSION	1		/* Contains a version string.  */
+
+
+/* Dynamic section entry.  */
+
+typedef struct
+{
+  Elf32_Sword	d_tag;			/* Dynamic entry type */
+  union
+    {
+      Elf32_Word d_val;			/* Integer value */
+      Elf32_Addr d_ptr;			/* Address value */
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword	d_tag;			/* Dynamic entry type */
+  union
+    {
+      Elf64_Xword d_val;		/* Integer value */
+      Elf64_Addr d_ptr;			/* Address value */
+    } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type).  */
+
+#define DT_NULL		0		/* Marks end of dynamic section */
+#define DT_NEEDED	1		/* Name of needed library */
+#define DT_PLTRELSZ	2		/* Size in bytes of PLT relocs */
+#define DT_PLTGOT	3		/* Processor defined value */
+#define DT_HASH		4		/* Address of symbol hash table */
+#define DT_STRTAB	5		/* Address of string table */
+#define DT_SYMTAB	6		/* Address of symbol table */
+#define DT_RELA		7		/* Address of Rela relocs */
+#define DT_RELASZ	8		/* Total size of Rela relocs */
+#define DT_RELAENT	9		/* Size of one Rela reloc */
+#define DT_STRSZ	10		/* Size of string table */
+#define DT_SYMENT	11		/* Size of one symbol table entry */
+#define DT_INIT		12		/* Address of init function */
+#define DT_FINI		13		/* Address of termination function */
+#define DT_SONAME	14		/* Name of shared object */
+#define DT_RPATH	15		/* Library search path (deprecated) */
+#define DT_SYMBOLIC	16		/* Start symbol search here */
+#define DT_REL		17		/* Address of Rel relocs */
+#define DT_RELSZ	18		/* Total size of Rel relocs */
+#define DT_RELENT	19		/* Size of one Rel reloc */
+#define DT_PLTREL	20		/* Type of reloc in PLT */
+#define DT_DEBUG	21		/* For debugging; unspecified */
+#define DT_TEXTREL	22		/* Reloc might modify .text */
+#define DT_JMPREL	23		/* Address of PLT relocs */
+#define	DT_BIND_NOW	24		/* Process relocations of object */
+#define	DT_INIT_ARRAY	25		/* Array with addresses of init fct */
+#define	DT_FINI_ARRAY	26		/* Array with addresses of fini fct */
+#define	DT_INIT_ARRAYSZ	27		/* Size in bytes of DT_INIT_ARRAY */
+#define	DT_FINI_ARRAYSZ	28		/* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH	29		/* Library search path */
+#define DT_FLAGS	30		/* Flags for the object being loaded */
+#define DT_ENCODING	32		/* Start of encoded range */
+#define DT_PREINIT_ARRAY 32		/* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33		/* size in bytes of DT_PREINIT_ARRAY */
+#define	DT_NUM		34		/* Number used */
+#define DT_LOOS		0x6000000d	/* Start of OS-specific */
+#define DT_HIOS		0x6ffff000	/* End of OS-specific */
+#define DT_LOPROC	0x70000000	/* Start of processor-specific */
+#define DT_HIPROC	0x7fffffff	/* End of processor-specific */
+#define	DT_PROCNUM	DT_MIPS_NUM	/* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+   approach.  */
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5	/* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6	/* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7	/* Size of library list */
+#define DT_CHECKSUM	0x6ffffdf8
+#define DT_PLTPADSZ	0x6ffffdf9
+#define DT_MOVEENT	0x6ffffdfa
+#define DT_MOVESZ	0x6ffffdfb
+#define DT_FEATURE_1	0x6ffffdfc	/* Feature selection (DTF_*).  */
+#define DT_POSFLAG_1	0x6ffffdfd	/* Flags for DT_* entries, effecting
+					   the following DT_* entry.  */
+#define DT_SYMINSZ	0x6ffffdfe	/* Size of syminfo table (in bytes) */
+#define DT_SYMINENT	0x6ffffdff	/* Entry size of syminfo */
+#define DT_VALRNGHI	0x6ffffdff
+#define DT_VALTAGIDX(tag)	(DT_VALRNGHI - (tag))	/* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+   If any adjustment is made to the ELF object after it has been
+   built these entries will need to be adjusted.  */
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_GNU_HASH	0x6ffffef5	/* GNU-style hash table.  */
+#define DT_TLSDESC_PLT	0x6ffffef6
+#define DT_TLSDESC_GOT	0x6ffffef7
+#define DT_GNU_CONFLICT	0x6ffffef8	/* Start of conflict section */
+#define DT_GNU_LIBLIST	0x6ffffef9	/* Library list */
+#define DT_CONFIG	0x6ffffefa	/* Configuration information.  */
+#define DT_DEPAUDIT	0x6ffffefb	/* Dependency auditing.  */
+#define DT_AUDIT	0x6ffffefc	/* Object auditing.  */
+#define	DT_PLTPAD	0x6ffffefd	/* PLT padding.  */
+#define	DT_MOVETAB	0x6ffffefe	/* Move table.  */
+#define DT_SYMINFO	0x6ffffeff	/* Syminfo table.  */
+#define DT_ADDRRNGHI	0x6ffffeff
+#define DT_ADDRTAGIDX(tag)	(DT_ADDRRNGHI - (tag))	/* Reverse order! */
+#define DT_ADDRNUM 11
+
+/* The versioning entry types.  The next are defined as part of the
+   GNU extension.  */
+#define DT_VERSYM	0x6ffffff0
+
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+
+/* These were chosen by Sun.  */
+#define DT_FLAGS_1	0x6ffffffb	/* State flags, see DF_1_* below.  */
+#define	DT_VERDEF	0x6ffffffc	/* Address of version definition
+					   table */
+#define	DT_VERDEFNUM	0x6ffffffd	/* Number of version definitions */
+#define	DT_VERNEED	0x6ffffffe	/* Address of table with needed
+					   versions */
+#define	DT_VERNEEDNUM	0x6fffffff	/* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag)	(DT_VERNEEDNUM - (tag))	/* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+   range.  Be compatible.  */
+#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
+#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag)	((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM	3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry.  */
+#define DF_ORIGIN	0x00000001	/* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC	0x00000002	/* Symbol resolutions starts here */
+#define DF_TEXTREL	0x00000004	/* Object contains text relocations */
+#define DF_BIND_NOW	0x00000008	/* No lazy binding for this object */
+#define DF_STATIC_TLS	0x00000010	/* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+   entry in the dynamic section.  */
+#define DF_1_NOW	0x00000001	/* Set RTLD_NOW for this object.  */
+#define DF_1_GLOBAL	0x00000002	/* Set RTLD_GLOBAL for this object.  */
+#define DF_1_GROUP	0x00000004	/* Set RTLD_GROUP for this object.  */
+#define DF_1_NODELETE	0x00000008	/* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR	0x00000010	/* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST	0x00000020	/* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN	0x00000040	/* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN	0x00000080	/* $ORIGIN must be handled.  */
+#define DF_1_DIRECT	0x00000100	/* Direct binding enabled.  */
+#define DF_1_TRANS	0x00000200
+#define DF_1_INTERPOSE	0x00000400	/* Object is used to interpose.  */
+#define DF_1_NODEFLIB	0x00000800	/* Ignore default lib search path.  */
+#define DF_1_NODUMP	0x00001000	/* Object can't be dldump'ed.  */
+#define DF_1_CONFALT	0x00002000	/* Configuration alternative created.*/
+#define DF_1_ENDFILTEE	0x00004000	/* Filtee terminates filters search. */
+#define	DF_1_DISPRELDNE	0x00008000	/* Disp reloc applied at build time. */
+#define	DF_1_DISPRELPND	0x00010000	/* Disp reloc applied at run-time.  */
+#define	DF_1_NODIRECT	0x00020000	/* Object has no-direct binding. */
+#define	DF_1_IGNMULDEF	0x00040000
+#define	DF_1_NOKSYMS	0x00080000
+#define	DF_1_NOHDR	0x00100000
+#define	DF_1_EDITED	0x00200000	/* Object is modified after built.  */
+#define	DF_1_NORELOC	0x00400000
+#define	DF_1_SYMINTPOSE	0x00800000	/* Object has individual interposers.  */
+#define	DF_1_GLOBAUDIT	0x01000000	/* Global auditing required.  */
+#define	DF_1_SINGLETON	0x02000000	/* Singleton symbols are used.  */
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT	0x00000001
+#define DTF_1_CONFEXP	0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD	0x00000001	/* Lazyload following object.  */
+#define DF_P1_GROUPPERM	0x00000002	/* Symbols from next object are not
+					   generally available.  */
+
+/* Version definition sections.  */
+
+typedef struct
+{
+  Elf32_Half	vd_version;		/* Version revision */
+  Elf32_Half	vd_flags;		/* Version information */
+  Elf32_Half	vd_ndx;			/* Version Index */
+  Elf32_Half	vd_cnt;			/* Number of associated aux entries */
+  Elf32_Word	vd_hash;		/* Version name hash value */
+  Elf32_Word	vd_aux;			/* Offset in bytes to verdaux array */
+  Elf32_Word	vd_next;		/* Offset in bytes to next verdef
+					   entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half	vd_version;		/* Version revision */
+  Elf64_Half	vd_flags;		/* Version information */
+  Elf64_Half	vd_ndx;			/* Version Index */
+  Elf64_Half	vd_cnt;			/* Number of associated aux entries */
+  Elf64_Word	vd_hash;		/* Version name hash value */
+  Elf64_Word	vd_aux;			/* Offset in bytes to verdaux array */
+  Elf64_Word	vd_next;		/* Offset in bytes to next verdef
+					   entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision).  */
+#define VER_DEF_NONE	0		/* No version */
+#define VER_DEF_CURRENT	1		/* Current version */
+#define VER_DEF_NUM	2		/* Given version number */
+
+/* Legal values for vd_flags (version information flags).  */
+#define VER_FLG_BASE	0x1		/* Version definition of file itself */
+#define VER_FLG_WEAK	0x2		/* Weak version identifier */
+
+/* Versym symbol index values.  */
+#define	VER_NDX_LOCAL		0	/* Symbol is local.  */
+#define	VER_NDX_GLOBAL		1	/* Symbol is global.  */
+#define	VER_NDX_LORESERVE	0xff00	/* Beginning of reserved entries.  */
+#define	VER_NDX_ELIMINATE	0xff01	/* Symbol is to be eliminated.  */
+
+/* Auxialiary version information.  */
+
+typedef struct
+{
+  Elf32_Word	vda_name;		/* Version or dependency names */
+  Elf32_Word	vda_next;		/* Offset in bytes to next verdaux
+					   entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word	vda_name;		/* Version or dependency names */
+  Elf64_Word	vda_next;		/* Offset in bytes to next verdaux
+					   entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section.  */
+
+typedef struct
+{
+  Elf32_Half	vn_version;		/* Version of structure */
+  Elf32_Half	vn_cnt;			/* Number of associated aux entries */
+  Elf32_Word	vn_file;		/* Offset of filename for this
+					   dependency */
+  Elf32_Word	vn_aux;			/* Offset in bytes to vernaux array */
+  Elf32_Word	vn_next;		/* Offset in bytes to next verneed
+					   entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half	vn_version;		/* Version of structure */
+  Elf64_Half	vn_cnt;			/* Number of associated aux entries */
+  Elf64_Word	vn_file;		/* Offset of filename for this
+					   dependency */
+  Elf64_Word	vn_aux;			/* Offset in bytes to vernaux array */
+  Elf64_Word	vn_next;		/* Offset in bytes to next verneed
+					   entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision).  */
+#define VER_NEED_NONE	 0		/* No version */
+#define VER_NEED_CURRENT 1		/* Current version */
+#define VER_NEED_NUM	 2		/* Given version number */
+
+/* Auxiliary needed version information.  */
+
+typedef struct
+{
+  Elf32_Word	vna_hash;		/* Hash value of dependency name */
+  Elf32_Half	vna_flags;		/* Dependency specific information */
+  Elf32_Half	vna_other;		/* Unused */
+  Elf32_Word	vna_name;		/* Dependency name string offset */
+  Elf32_Word	vna_next;		/* Offset in bytes to next vernaux
+					   entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word	vna_hash;		/* Hash value of dependency name */
+  Elf64_Half	vna_flags;		/* Dependency specific information */
+  Elf64_Half	vna_other;		/* Unused */
+  Elf64_Word	vna_name;		/* Dependency name string offset */
+  Elf64_Word	vna_next;		/* Offset in bytes to next vernaux
+					   entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags.  */
+#define VER_FLG_WEAK	0x2		/* Weak version identifier */
+
+
+/* Auxiliary vector.  */
+
+/* This vector is normally only used by the program interpreter.  The
+   usual definition in an ABI supplement uses the name auxv_t.  The
+   vector is not usually defined in a standard <elf.h> file, but it
+   can't hurt.  We rename it to avoid conflicts.  The sizes of these
+   types are an arrangement between the exec server and the program
+   interpreter, so we don't fully specify them here.  */
+
+typedef struct
+{
+  uint32_t a_type;		/* Entry type */
+  union
+    {
+      uint32_t a_val;		/* Integer value */
+      /* We use to have pointer elements added here.  We cannot do that,
+	 though, since it does not work when using 32-bit definitions
+	 on 64-bit platforms and vice versa.  */
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  uint64_t a_type;		/* Entry type */
+  union
+    {
+      uint64_t a_val;		/* Integer value */
+      /* We use to have pointer elements added here.  We cannot do that,
+	 though, since it does not work when using 32-bit definitions
+	 on 64-bit platforms and vice versa.  */
+    } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type).  */
+
+#define AT_NULL		0		/* End of vector */
+#define AT_IGNORE	1		/* Entry should be ignored */
+#define AT_EXECFD	2		/* File descriptor of program */
+#define AT_PHDR		3		/* Program headers for program */
+#define AT_PHENT	4		/* Size of program header entry */
+#define AT_PHNUM	5		/* Number of program headers */
+#define AT_PAGESZ	6		/* System page size */
+#define AT_BASE		7		/* Base address of interpreter */
+#define AT_FLAGS	8		/* Flags */
+#define AT_ENTRY	9		/* Entry point of program */
+#define AT_NOTELF	10		/* Program is not ELF */
+#define AT_UID		11		/* Real uid */
+#define AT_EUID		12		/* Effective uid */
+#define AT_GID		13		/* Real gid */
+#define AT_EGID		14		/* Effective gid */
+#define AT_CLKTCK	17		/* Frequency of times() */
+
+/* Some more special a_type values describing the hardware.  */
+#define AT_PLATFORM	15		/* String identifying platform.  */
+#define AT_HWCAP	16		/* Machine-dependent hints about
+					   processor capabilities.  */
+
+/* This entry gives some information about the FPU initialization
+   performed by the kernel.  */
+#define AT_FPUCW	18		/* Used FPU control word.  */
+
+/* Cache block sizes.  */
+#define AT_DCACHEBSIZE	19		/* Data cache block size.  */
+#define AT_ICACHEBSIZE	20		/* Instruction cache block size.  */
+#define AT_UCACHEBSIZE	21		/* Unified cache block size.  */
+
+/* A special ignored value for PPC, used by the kernel to control the
+   interpretation of the AUXV. Must be > 16.  */
+#define AT_IGNOREPPC	22		/* Entry should be ignored.  */
+
+#define	AT_SECURE	23		/* Boolean, was exec setuid-like?  */
+
+#define AT_BASE_PLATFORM 24		/* String identifying real platforms.*/
+
+#define AT_RANDOM	25		/* Address of 16 random bytes.  */
+
+#define AT_HWCAP2	26		/* More machine-dependent hints about
+					   processor capabilities.  */
+
+#define AT_EXECFN	31		/* Filename of executable.  */
+
+/* Pointer to the global system page used for system calls and other
+   nice things.  */
+#define AT_SYSINFO	32
+#define AT_SYSINFO_EHDR	33
+
+/* Shapes of the caches.  Bits 0-3 contains associativity; bits 4-7 contains
+   log2 of line size; mask those to get cache size.  */
+#define AT_L1I_CACHESHAPE	34
+#define AT_L1D_CACHESHAPE	35
+#define AT_L2_CACHESHAPE	36
+#define AT_L3_CACHESHAPE	37
+
+/* Shapes of the caches, with more room to describe them.
+   *GEOMETRY are comprised of cache line size in bytes in the bottom 16 bits
+   and the cache associativity in the next 16 bits.  */
+#define AT_L1I_CACHESIZE	40
+#define AT_L1I_CACHEGEOMETRY	41
+#define AT_L1D_CACHESIZE	42
+#define AT_L1D_CACHEGEOMETRY	43
+#define AT_L2_CACHESIZE		44
+#define AT_L2_CACHEGEOMETRY	45
+#define AT_L3_CACHESIZE		46
+#define AT_L3_CACHEGEOMETRY	47
+
+/* Note section contents.  Each entry in the note section begins with
+   a header of a fixed form.  */
+
+typedef struct
+{
+  Elf32_Word n_namesz;			/* Length of the note's name.  */
+  Elf32_Word n_descsz;			/* Length of the note's descriptor.  */
+  Elf32_Word n_type;			/* Type of the note.  */
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;			/* Length of the note's name.  */
+  Elf64_Word n_descsz;			/* Length of the note's descriptor.  */
+  Elf64_Word n_type;			/* Type of the note.  */
+} Elf64_Nhdr;
+
+/* Known names of notes.  */
+
+/* Solaris entries in the note section have this name.  */
+#define ELF_NOTE_SOLARIS	"SUNW Solaris"
+
+/* Note entries for GNU systems have this name.  */
+#define ELF_NOTE_GNU		"GNU"
+
+
+/* Defined types of notes for Solaris.  */
+
+/* Value of descriptor (one word) is desired pagesize for the binary.  */
+#define ELF_NOTE_PAGESIZE_HINT	1
+
+
+/* Defined note types for GNU systems.  */
+
+/* ABI information.  The descriptor consists of words:
+   word 0: OS descriptor
+   word 1: major version of the ABI
+   word 2: minor version of the ABI
+   word 3: subminor version of the ABI
+*/
+#define NT_GNU_ABI_TAG	1
+#define ELF_NOTE_ABI	NT_GNU_ABI_TAG /* Old name.  */
+
+/* Known OSes.  These values can appear in word 0 of an
+   NT_GNU_ABI_TAG note section entry.  */
+#define ELF_NOTE_OS_LINUX	0
+#define ELF_NOTE_OS_GNU		1
+#define ELF_NOTE_OS_SOLARIS2	2
+#define ELF_NOTE_OS_FREEBSD	3
+
+/* Synthetic hwcap information.  The descriptor begins with two words:
+   word 0: number of entries
+   word 1: bitmask of enabled entries
+   Then follow variable-length entries, one byte followed by a
+   '\0'-terminated hwcap name string.  The byte gives the bit
+   number to test if enabled, (1U << bit) & bitmask.  */
+#define NT_GNU_HWCAP	2
+
+/* Build ID bits as generated by ld --build-id.
+   The descriptor consists of any nonzero number of bytes.  */
+#define NT_GNU_BUILD_ID	3
+
+/* Version note generated by GNU gold containing a version string.  */
+#define NT_GNU_GOLD_VERSION	4
+
+
+/* Move records.  */
+typedef struct
+{
+  Elf32_Xword m_value;		/* Symbol value.  */
+  Elf32_Word m_info;		/* Size and index.  */
+  Elf32_Word m_poffset;		/* Symbol offset.  */
+  Elf32_Half m_repeat;		/* Repeat count.  */
+  Elf32_Half m_stride;		/* Stride info.  */
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;		/* Symbol value.  */
+  Elf64_Xword m_info;		/* Size and index.  */
+  Elf64_Xword m_poffset;	/* Symbol offset.  */
+  Elf64_Half m_repeat;		/* Repeat count.  */
+  Elf64_Half m_stride;		/* Stride info.  */
+} Elf64_Move;
+
+/* Macro to construct move records.  */
+#define ELF32_M_SYM(info)	((info) >> 8)
+#define ELF32_M_SIZE(info)	((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)	(((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)	ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)	ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)	ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions.  */
+
+/* Values for Elf32_Ehdr.e_flags.  */
+#define EF_CPU32	0x00810000
+
+/* m68k relocs.  */
+
+#define R_68K_NONE	0		/* No reloc */
+#define R_68K_32	1		/* Direct 32 bit  */
+#define R_68K_16	2		/* Direct 16 bit  */
+#define R_68K_8		3		/* Direct 8 bit  */
+#define R_68K_PC32	4		/* PC relative 32 bit */
+#define R_68K_PC16	5		/* PC relative 16 bit */
+#define R_68K_PC8	6		/* PC relative 8 bit */
+#define R_68K_GOT32	7		/* 32 bit PC relative GOT entry */
+#define R_68K_GOT16	8		/* 16 bit PC relative GOT entry */
+#define R_68K_GOT8	9		/* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O	10		/* 32 bit GOT offset */
+#define R_68K_GOT16O	11		/* 16 bit GOT offset */
+#define R_68K_GOT8O	12		/* 8 bit GOT offset */
+#define R_68K_PLT32	13		/* 32 bit PC relative PLT address */
+#define R_68K_PLT16	14		/* 16 bit PC relative PLT address */
+#define R_68K_PLT8	15		/* 8 bit PC relative PLT address */
+#define R_68K_PLT32O	16		/* 32 bit PLT offset */
+#define R_68K_PLT16O	17		/* 16 bit PLT offset */
+#define R_68K_PLT8O	18		/* 8 bit PLT offset */
+#define R_68K_COPY	19		/* Copy symbol at runtime */
+#define R_68K_GLOB_DAT	20		/* Create GOT entry */
+#define R_68K_JMP_SLOT	21		/* Create PLT entry */
+#define R_68K_RELATIVE	22		/* Adjust by program base */
+#define R_68K_TLS_GD32      25          /* 32 bit GOT offset for GD */
+#define R_68K_TLS_GD16      26          /* 16 bit GOT offset for GD */
+#define R_68K_TLS_GD8       27          /* 8 bit GOT offset for GD */
+#define R_68K_TLS_LDM32     28          /* 32 bit GOT offset for LDM */
+#define R_68K_TLS_LDM16     29          /* 16 bit GOT offset for LDM */
+#define R_68K_TLS_LDM8      30          /* 8 bit GOT offset for LDM */
+#define R_68K_TLS_LDO32     31          /* 32 bit module-relative offset */
+#define R_68K_TLS_LDO16     32          /* 16 bit module-relative offset */
+#define R_68K_TLS_LDO8      33          /* 8 bit module-relative offset */
+#define R_68K_TLS_IE32      34          /* 32 bit GOT offset for IE */
+#define R_68K_TLS_IE16      35          /* 16 bit GOT offset for IE */
+#define R_68K_TLS_IE8       36          /* 8 bit GOT offset for IE */
+#define R_68K_TLS_LE32      37          /* 32 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_LE16      38          /* 16 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_LE8       39          /* 8 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_DTPMOD32  40          /* 32 bit module number */
+#define R_68K_TLS_DTPREL32  41          /* 32 bit module-relative offset */
+#define R_68K_TLS_TPREL32   42          /* 32 bit TP-relative offset */
+/* Keep this the last entry.  */
+#define R_68K_NUM	43
+
+/* Intel 80386 specific definitions.  */
+
+/* i386 relocs.  */
+
+#define R_386_NONE	   0		/* No reloc */
+#define R_386_32	   1		/* Direct 32 bit  */
+#define R_386_PC32	   2		/* PC relative 32 bit */
+#define R_386_GOT32	   3		/* 32 bit GOT entry */
+#define R_386_PLT32	   4		/* 32 bit PLT address */
+#define R_386_COPY	   5		/* Copy symbol at runtime */
+#define R_386_GLOB_DAT	   6		/* Create GOT entry */
+#define R_386_JMP_SLOT	   7		/* Create PLT entry */
+#define R_386_RELATIVE	   8		/* Adjust by program base */
+#define R_386_GOTOFF	   9		/* 32 bit offset to GOT */
+#define R_386_GOTPC	   10		/* 32 bit PC relative offset to GOT */
+#define R_386_32PLT	   11
+#define R_386_TLS_TPOFF	   14		/* Offset in static TLS block */
+#define R_386_TLS_IE	   15		/* Address of GOT entry for static TLS
+					   block offset */
+#define R_386_TLS_GOTIE	   16		/* GOT entry for static TLS block
+					   offset */
+#define R_386_TLS_LE	   17		/* Offset relative to static TLS
+					   block */
+#define R_386_TLS_GD	   18		/* Direct 32 bit for GNU version of
+					   general dynamic thread local data */
+#define R_386_TLS_LDM	   19		/* Direct 32 bit for GNU version of
+					   local dynamic thread local data
+					   in LE code */
+#define R_386_16	   20
+#define R_386_PC16	   21
+#define R_386_8		   22
+#define R_386_PC8	   23
+#define R_386_TLS_GD_32	   24		/* Direct 32 bit for general dynamic
+					   thread local data */
+#define R_386_TLS_GD_PUSH  25		/* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL  26		/* Relocation for call to
+					   __tls_get_addr() */
+#define R_386_TLS_GD_POP   27		/* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32   28		/* Direct 32 bit for local dynamic
+					   thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29		/* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30		/* Relocation for call to
+					   __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP  31		/* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32   32		/* Offset relative to TLS block */
+#define R_386_TLS_IE_32	   33		/* GOT entry for negated static TLS
+					   block offset */
+#define R_386_TLS_LE_32	   34		/* Negated offset relative to static
+					   TLS block */
+#define R_386_TLS_DTPMOD32 35		/* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36		/* Offset in TLS block */
+#define R_386_TLS_TPOFF32  37		/* Negated offset in static TLS block */
+#define R_386_SIZE32	   38 		/* 32-bit symbol size */
+#define R_386_TLS_GOTDESC  39		/* GOT offset for TLS descriptor.  */
+#define R_386_TLS_DESC_CALL 40		/* Marker of call through TLS
+					   descriptor for
+					   relaxation.  */
+#define R_386_TLS_DESC     41		/* TLS descriptor containing
+					   pointer to code and to
+					   argument, returning the TLS
+					   offset for the symbol.  */
+#define R_386_IRELATIVE	   42		/* Adjust indirectly by program base */
+#define R_386_GOT32X	   43		/* Load from 32 bit GOT entry,
+					   relaxable. */
+/* Keep this the last entry.  */
+#define R_386_NUM	   44
+
+/* SUN SPARC specific definitions.  */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_SPARC_REGISTER	13	/* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM		3
+#define EF_SPARCV9_TSO		0
+#define EF_SPARCV9_PSO		1
+#define EF_SPARCV9_RMO		2
+#define EF_SPARC_LEDATA		0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK	0xFFFF00
+#define EF_SPARC_32PLUS		0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1	0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1		0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3	0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs.  */
+
+#define R_SPARC_NONE		0	/* No reloc */
+#define R_SPARC_8		1	/* Direct 8 bit */
+#define R_SPARC_16		2	/* Direct 16 bit */
+#define R_SPARC_32		3	/* Direct 32 bit */
+#define R_SPARC_DISP8		4	/* PC relative 8 bit */
+#define R_SPARC_DISP16		5	/* PC relative 16 bit */
+#define R_SPARC_DISP32		6	/* PC relative 32 bit */
+#define R_SPARC_WDISP30		7	/* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22		8	/* PC relative 22 bit shifted */
+#define R_SPARC_HI22		9	/* High 22 bit */
+#define R_SPARC_22		10	/* Direct 22 bit */
+#define R_SPARC_13		11	/* Direct 13 bit */
+#define R_SPARC_LO10		12	/* Truncated 10 bit */
+#define R_SPARC_GOT10		13	/* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13		14	/* 13 bit GOT entry */
+#define R_SPARC_GOT22		15	/* 22 bit GOT entry shifted */
+#define R_SPARC_PC10		16	/* PC relative 10 bit truncated */
+#define R_SPARC_PC22		17	/* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30		18	/* 30 bit PC relative PLT address */
+#define R_SPARC_COPY		19	/* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT	20	/* Create GOT entry */
+#define R_SPARC_JMP_SLOT	21	/* Create PLT entry */
+#define R_SPARC_RELATIVE	22	/* Adjust by program base */
+#define R_SPARC_UA32		23	/* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs.  */
+
+#define R_SPARC_PLT32		24	/* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22		25	/* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10		26	/* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32		27	/* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22		28	/* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10		29	/* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10		30	/* Direct 10 bit */
+#define R_SPARC_11		31	/* Direct 11 bit */
+#define R_SPARC_64		32	/* Direct 64 bit */
+#define R_SPARC_OLO10		33	/* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22		34	/* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10		35	/* High middle 10 bits of ... */
+#define R_SPARC_LM22		36	/* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22		37	/* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10		38	/* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22		39	/* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16		40	/* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19		41	/* PC relative 19 bit shifted */
+#define R_SPARC_GLOB_JMP	42	/* was part of v9 ABI but was removed */
+#define R_SPARC_7		43	/* Direct 7 bit */
+#define R_SPARC_5		44	/* Direct 5 bit */
+#define R_SPARC_6		45	/* Direct 6 bit */
+#define R_SPARC_DISP64		46	/* PC relative 64 bit */
+#define R_SPARC_PLT64		47	/* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22		48	/* High 22 bit complemented */
+#define R_SPARC_LOX10		49	/* Truncated 11 bit complemented */
+#define R_SPARC_H44		50	/* Direct high 12 of 44 bit */
+#define R_SPARC_M44		51	/* Direct mid 22 of 44 bit */
+#define R_SPARC_L44		52	/* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER	53	/* Global register usage */
+#define R_SPARC_UA64		54	/* Direct 64 bit unaligned */
+#define R_SPARC_UA16		55	/* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22	56
+#define R_SPARC_TLS_GD_LO10	57
+#define R_SPARC_TLS_GD_ADD	58
+#define R_SPARC_TLS_GD_CALL	59
+#define R_SPARC_TLS_LDM_HI22	60
+#define R_SPARC_TLS_LDM_LO10	61
+#define R_SPARC_TLS_LDM_ADD	62
+#define R_SPARC_TLS_LDM_CALL	63
+#define R_SPARC_TLS_LDO_HIX22	64
+#define R_SPARC_TLS_LDO_LOX10	65
+#define R_SPARC_TLS_LDO_ADD	66
+#define R_SPARC_TLS_IE_HI22	67
+#define R_SPARC_TLS_IE_LO10	68
+#define R_SPARC_TLS_IE_LD	69
+#define R_SPARC_TLS_IE_LDX	70
+#define R_SPARC_TLS_IE_ADD	71
+#define R_SPARC_TLS_LE_HIX22	72
+#define R_SPARC_TLS_LE_LOX10	73
+#define R_SPARC_TLS_DTPMOD32	74
+#define R_SPARC_TLS_DTPMOD64	75
+#define R_SPARC_TLS_DTPOFF32	76
+#define R_SPARC_TLS_DTPOFF64	77
+#define R_SPARC_TLS_TPOFF32	78
+#define R_SPARC_TLS_TPOFF64	79
+#define R_SPARC_GOTDATA_HIX22	80
+#define R_SPARC_GOTDATA_LOX10	81
+#define R_SPARC_GOTDATA_OP_HIX22	82
+#define R_SPARC_GOTDATA_OP_LOX10	83
+#define R_SPARC_GOTDATA_OP	84
+#define R_SPARC_H34		85
+#define R_SPARC_SIZE32		86
+#define R_SPARC_SIZE64		87
+#define R_SPARC_WDISP10		88
+#define R_SPARC_JMP_IREL	248
+#define R_SPARC_IRELATIVE	249
+#define R_SPARC_GNU_VTINHERIT	250
+#define R_SPARC_GNU_VTENTRY	251
+#define R_SPARC_REV32		252
+/* Keep this the last entry.  */
+#define R_SPARC_NUM		253
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
+
+#define DT_SPARC_REGISTER	0x70000001
+#define DT_SPARC_NUM		2
+
+/* MIPS R3000 specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_MIPS_NOREORDER	1     /* A .noreorder directive was used.  */
+#define EF_MIPS_PIC		2     /* Contains PIC code.  */
+#define EF_MIPS_CPIC		4     /* Uses PIC calling sequence.  */
+#define EF_MIPS_XGOT		8
+#define EF_MIPS_64BIT_WHIRL	16
+#define EF_MIPS_ABI2		32
+#define EF_MIPS_ABI_ON32	64
+#define EF_MIPS_FP64		512  /* Uses FP64 (12 callee-saved).  */
+#define EF_MIPS_NAN2008	1024  /* Uses IEEE 754-2008 NaN encoding.  */
+#define EF_MIPS_ARCH		0xf0000000 /* MIPS architecture level.  */
+
+/* Legal values for MIPS architecture level.  */
+
+#define EF_MIPS_ARCH_1		0x00000000 /* -mips1 code.  */
+#define EF_MIPS_ARCH_2		0x10000000 /* -mips2 code.  */
+#define EF_MIPS_ARCH_3		0x20000000 /* -mips3 code.  */
+#define EF_MIPS_ARCH_4		0x30000000 /* -mips4 code.  */
+#define EF_MIPS_ARCH_5		0x40000000 /* -mips5 code.  */
+#define EF_MIPS_ARCH_32		0x50000000 /* MIPS32 code.  */
+#define EF_MIPS_ARCH_64		0x60000000 /* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2	0x70000000 /* MIPS32r2 code.  */
+#define EF_MIPS_ARCH_64R2	0x80000000 /* MIPS64r2 code.  */
+
+/* The following are unofficial names and should not be used.  */
+
+#define E_MIPS_ARCH_1		EF_MIPS_ARCH_1
+#define E_MIPS_ARCH_2		EF_MIPS_ARCH_2
+#define E_MIPS_ARCH_3		EF_MIPS_ARCH_3
+#define E_MIPS_ARCH_4		EF_MIPS_ARCH_4
+#define E_MIPS_ARCH_5		EF_MIPS_ARCH_5
+#define E_MIPS_ARCH_32		EF_MIPS_ARCH_32
+#define E_MIPS_ARCH_64		EF_MIPS_ARCH_64
+
+/* Special section indices.  */
+
+#define SHN_MIPS_ACOMMON	0xff00	/* Allocated common symbols.  */
+#define SHN_MIPS_TEXT		0xff01	/* Allocated test symbols.  */
+#define SHN_MIPS_DATA		0xff02	/* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON 	0xff03	/* Small common symbols.  */
+#define SHN_MIPS_SUNDEFINED	0xff04	/* Small undefined symbols.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_MIPS_LIBLIST	0x70000000 /* Shared objects used in link.  */
+#define SHT_MIPS_MSYM		0x70000001
+#define SHT_MIPS_CONFLICT	0x70000002 /* Conflicting symbols.  */
+#define SHT_MIPS_GPTAB		0x70000003 /* Global data area sizes.  */
+#define SHT_MIPS_UCODE		0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG		0x70000005 /* MIPS ECOFF debugging info.  */
+#define SHT_MIPS_REGINFO	0x70000006 /* Register usage information.  */
+#define SHT_MIPS_PACKAGE	0x70000007
+#define SHT_MIPS_PACKSYM	0x70000008
+#define SHT_MIPS_RELD		0x70000009
+#define SHT_MIPS_IFACE		0x7000000b
+#define SHT_MIPS_CONTENT	0x7000000c
+#define SHT_MIPS_OPTIONS	0x7000000d /* Miscellaneous options.  */
+#define SHT_MIPS_SHDR		0x70000010
+#define SHT_MIPS_FDESC		0x70000011
+#define SHT_MIPS_EXTSYM		0x70000012
+#define SHT_MIPS_DENSE		0x70000013
+#define SHT_MIPS_PDESC		0x70000014
+#define SHT_MIPS_LOCSYM		0x70000015
+#define SHT_MIPS_AUXSYM		0x70000016
+#define SHT_MIPS_OPTSYM		0x70000017
+#define SHT_MIPS_LOCSTR		0x70000018
+#define SHT_MIPS_LINE		0x70000019
+#define SHT_MIPS_RFDESC		0x7000001a
+#define SHT_MIPS_DELTASYM	0x7000001b
+#define SHT_MIPS_DELTAINST	0x7000001c
+#define SHT_MIPS_DELTACLASS	0x7000001d
+#define SHT_MIPS_DWARF		0x7000001e /* DWARF debugging information.  */
+#define SHT_MIPS_DELTADECL	0x7000001f
+#define SHT_MIPS_SYMBOL_LIB	0x70000020
+#define SHT_MIPS_EVENTS		0x70000021 /* Event section.  */
+#define SHT_MIPS_TRANSLATE	0x70000022
+#define SHT_MIPS_PIXIE		0x70000023
+#define SHT_MIPS_XLATE		0x70000024
+#define SHT_MIPS_XLATE_DEBUG	0x70000025
+#define SHT_MIPS_WHIRL		0x70000026
+#define SHT_MIPS_EH_REGION	0x70000027
+#define SHT_MIPS_XLATE_OLD	0x70000028
+#define SHT_MIPS_PDR_EXCEPTION	0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_MIPS_GPREL		0x10000000 /* Must be in global data area.  */
+#define SHF_MIPS_MERGE		0x20000000
+#define SHF_MIPS_ADDR		0x40000000
+#define SHF_MIPS_STRINGS	0x80000000
+#define SHF_MIPS_NOSTRIP	0x08000000
+#define SHF_MIPS_LOCAL		0x04000000
+#define SHF_MIPS_NAMES		0x02000000
+#define SHF_MIPS_NODUPE		0x01000000
+
+
+/* Symbol tables.  */
+
+/* MIPS specific values for `st_other'.  */
+#define STO_MIPS_DEFAULT		0x0
+#define STO_MIPS_INTERNAL		0x1
+#define STO_MIPS_HIDDEN			0x2
+#define STO_MIPS_PROTECTED		0x3
+#define STO_MIPS_PLT			0x8
+#define STO_MIPS_SC_ALIGN_UNUSED	0xff
+
+/* MIPS specific values for `st_info'.  */
+#define STB_MIPS_SPLIT_COMMON		13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB.  */
+
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;	/* -G value used for compilation.  */
+      Elf32_Word gt_unused;		/* Not used.  */
+    } gt_header;			/* First entry in section.  */
+  struct
+    {
+      Elf32_Word gt_g_value;		/* If this value were used for -G.  */
+      Elf32_Word gt_bytes;		/* This many bytes would be used.  */
+    } gt_entry;				/* Subsequent entries in section.  */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO.  */
+
+typedef struct
+{
+  Elf32_Word ri_gprmask;		/* General registers used.  */
+  Elf32_Word ri_cprmask[4];		/* Coprocessor registers used.  */
+  Elf32_Sword ri_gp_value;		/* $gp register value.  */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
+
+typedef struct
+{
+  unsigned char kind;		/* Determines interpretation of the
+				   variable part of descriptor.  */
+  unsigned char size;		/* Size of descriptor, including header.  */
+  Elf32_Section section;	/* Section header index of section affected,
+				   0 for global options.  */
+  Elf32_Word info;		/* Kind-specific information.  */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options.  */
+
+#define ODK_NULL	0	/* Undefined.  */
+#define ODK_REGINFO	1	/* Register usage information.  */
+#define ODK_EXCEPTIONS	2	/* Exception processing options.  */
+#define ODK_PAD		3	/* Section padding options.  */
+#define ODK_HWPATCH	4	/* Hardware workarounds performed */
+#define ODK_FILL	5	/* record the fill value used by the linker. */
+#define ODK_TAGS	6	/* reserve space for desktop tools to write. */
+#define ODK_HWAND	7	/* HW workarounds.  'AND' bits when merging. */
+#define ODK_HWOR	8	/* HW workarounds.  'OR' bits when merging.  */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
+
+#define OEX_FPU_MIN	0x1f	/* FPE's which MUST be enabled.  */
+#define OEX_FPU_MAX	0x1f00	/* FPE's which MAY be enabled.  */
+#define OEX_PAGE0	0x10000	/* page zero must be mapped.  */
+#define OEX_SMM		0x20000	/* Force sequential memory mode?  */
+#define OEX_FPDBUG	0x40000	/* Force floating point debug mode?  */
+#define OEX_PRECISEFP	OEX_FPDBUG
+#define OEX_DISMISS	0x80000	/* Dismiss invalid address faults?  */
+
+#define OEX_FPU_INVAL	0x10
+#define OEX_FPU_DIV0	0x08
+#define OEX_FPU_OFLO	0x04
+#define OEX_FPU_UFLO	0x02
+#define OEX_FPU_INEX	0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
+
+#define OHW_R4KEOP	0x1	/* R4000 end-of-page patch.  */
+#define OHW_R8KPFETCH	0x2	/* may need R8000 prefetch patch.  */
+#define OHW_R5KEOP	0x4	/* R5000 end-of-page patch.  */
+#define OHW_R5KCVTL	0x8	/* R5000 cvt.[ds].l bug.  clean=1.  */
+
+#define OPAD_PREFIX	0x1
+#define OPAD_POSTFIX	0x2
+#define OPAD_SYMBOL	0x4
+
+/* Entry found in `.options' section.  */
+
+typedef struct
+{
+  Elf32_Word hwp_flags1;	/* Extra flags.  */
+  Elf32_Word hwp_flags2;	/* Extra flags.  */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
+
+#define OHWA0_R4KEOP_CHECKED	0x00000001
+#define OHWA1_R4KEOP_CLEAN	0x00000002
+
+/* MIPS relocs.  */
+
+#define R_MIPS_NONE		0	/* No reloc */
+#define R_MIPS_16		1	/* Direct 16 bit */
+#define R_MIPS_32		2	/* Direct 32 bit */
+#define R_MIPS_REL32		3	/* PC relative 32 bit */
+#define R_MIPS_26		4	/* Direct 26 bit shifted */
+#define R_MIPS_HI16		5	/* High 16 bit */
+#define R_MIPS_LO16		6	/* Low 16 bit */
+#define R_MIPS_GPREL16		7	/* GP relative 16 bit */
+#define R_MIPS_LITERAL		8	/* 16 bit literal entry */
+#define R_MIPS_GOT16		9	/* 16 bit GOT entry */
+#define R_MIPS_PC16		10	/* PC relative 16 bit */
+#define R_MIPS_CALL16		11	/* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32		12	/* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5		16
+#define R_MIPS_SHIFT6		17
+#define R_MIPS_64		18
+#define R_MIPS_GOT_DISP		19
+#define R_MIPS_GOT_PAGE		20
+#define R_MIPS_GOT_OFST		21
+#define R_MIPS_GOT_HI16		22
+#define R_MIPS_GOT_LO16		23
+#define R_MIPS_SUB		24
+#define R_MIPS_INSERT_A		25
+#define R_MIPS_INSERT_B		26
+#define R_MIPS_DELETE		27
+#define R_MIPS_HIGHER		28
+#define R_MIPS_HIGHEST		29
+#define R_MIPS_CALL_HI16	30
+#define R_MIPS_CALL_LO16	31
+#define R_MIPS_SCN_DISP		32
+#define R_MIPS_REL16		33
+#define R_MIPS_ADD_IMMEDIATE	34
+#define R_MIPS_PJUMP		35
+#define R_MIPS_RELGOT		36
+#define R_MIPS_JALR		37
+#define R_MIPS_TLS_DTPMOD32	38	/* Module number 32 bit */
+#define R_MIPS_TLS_DTPREL32	39	/* Module-relative offset 32 bit */
+#define R_MIPS_TLS_DTPMOD64	40	/* Module number 64 bit */
+#define R_MIPS_TLS_DTPREL64	41	/* Module-relative offset 64 bit */
+#define R_MIPS_TLS_GD		42	/* 16 bit GOT offset for GD */
+#define R_MIPS_TLS_LDM		43	/* 16 bit GOT offset for LDM */
+#define R_MIPS_TLS_DTPREL_HI16	44	/* Module-relative offset, high 16 bits */
+#define R_MIPS_TLS_DTPREL_LO16	45	/* Module-relative offset, low 16 bits */
+#define R_MIPS_TLS_GOTTPREL	46	/* 16 bit GOT offset for IE */
+#define R_MIPS_TLS_TPREL32	47	/* TP-relative offset, 32 bit */
+#define R_MIPS_TLS_TPREL64	48	/* TP-relative offset, 64 bit */
+#define R_MIPS_TLS_TPREL_HI16	49	/* TP-relative offset, high 16 bits */
+#define R_MIPS_TLS_TPREL_LO16	50	/* TP-relative offset, low 16 bits */
+#define R_MIPS_GLOB_DAT		51
+#define R_MIPS_COPY		126
+#define R_MIPS_JUMP_SLOT        127
+/* Keep this the last entry.  */
+#define R_MIPS_NUM		128
+
+/* Legal values for p_type field of Elf32_Phdr.  */
+
+#define PT_MIPS_REGINFO	  0x70000000	/* Register usage information. */
+#define PT_MIPS_RTPROC	  0x70000001	/* Runtime procedure table. */
+#define PT_MIPS_OPTIONS	  0x70000002
+#define PT_MIPS_ABIFLAGS  0x70000003	/* FP mode requirement. */
+
+/* Special program header types.  */
+
+#define PF_MIPS_LOCAL	0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn.  */
+
+#define DT_MIPS_RLD_VERSION  0x70000001	/* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP   0x70000002	/* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003	/* Checksum */
+#define DT_MIPS_IVERSION     0x70000004	/* Version string (string tbl index) */
+#define DT_MIPS_FLAGS	     0x70000005	/* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006	/* Base address */
+#define DT_MIPS_MSYM	     0x70000007
+#define DT_MIPS_CONFLICT     0x70000008	/* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST	     0x70000009	/* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a	/* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b	/* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO    0x70000010	/* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO     0x70000011	/* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012	/* First external DYNSYM */
+#define DT_MIPS_GOTSYM	     0x70000013	/* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO     0x70000014	/* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP	     0x70000016	/* Address of run time loader map.  */
+#define DT_MIPS_DELTA_CLASS  0x70000017	/* Delta C++ class definition.  */
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
+						DT_MIPS_DELTA_CLASS.  */
+#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+						DT_MIPS_DELTA_INSTANCE.  */
+#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+					     DT_MIPS_DELTA_RELOC.  */
+#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
+					   relocations refer to.  */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+					   DT_MIPS_DELTA_SYM.  */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+					     class declaration.  */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+						DT_MIPS_DELTA_CLASSSYM.  */
+#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS	     0x70000029 /* Address of .options.  */
+#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+						    function stored in GOT.  */
+#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
+					   by rld on dlopen() calls.  */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
+#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
+/* The address of .got.plt in an executable using the new non-PIC ABI.  */
+#define DT_MIPS_PLTGOT	     0x70000032
+/* The base of the PLT in an executable using the new non-PIC ABI if that
+   PLT is writable.  For a non-writable PLT, this is omitted or has a zero
+   value.  */
+#define DT_MIPS_RWPLT        0x70000034
+/* An alternative description of the classic MIPS RLD_MAP that is usable
+   in a PIE as it stores a relative offset from the address of the tag
+   rather than an absolute address.  */
+#define DT_MIPS_RLD_MAP_REL  0x70000035
+#define DT_MIPS_NUM	     0x36
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
+
+#define RHF_NONE		   0		/* No flags */
+#define RHF_QUICKSTART		   (1 << 0)	/* Use quickstart */
+#define RHF_NOTPOT		   (1 << 1)	/* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)	/* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE		   (1 << 3)
+#define RHF_SGI_ONLY		   (1 << 4)
+#define RHF_GUARANTEE_INIT	   (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS	   (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE		   (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD	   (1 << 9)
+#define RHF_REQUICKSTART	   (1 << 10)
+#define RHF_REQUICKSTARTED	   (1 << 11)
+#define RHF_CORD		   (1 << 12)
+#define RHF_NO_UNRES_UNDEF	   (1 << 13)
+#define RHF_RLD_ORDER_SAFE	   (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
+
+typedef struct
+{
+  Elf32_Word l_name;		/* Name (string table index) */
+  Elf32_Word l_time_stamp;	/* Timestamp */
+  Elf32_Word l_checksum;	/* Checksum */
+  Elf32_Word l_version;		/* Interface version */
+  Elf32_Word l_flags;		/* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;		/* Name (string table index) */
+  Elf64_Word l_time_stamp;	/* Timestamp */
+  Elf64_Word l_checksum;	/* Checksum */
+  Elf64_Word l_version;		/* Interface version */
+  Elf64_Word l_flags;		/* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags.  */
+
+#define LL_NONE		  0
+#define LL_EXACT_MATCH	  (1 << 0)	/* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1)	/* Ignore interface version */
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS	  (1 << 3)
+#define LL_DELAY_LOAD	  (1 << 4)
+#define LL_DELTA	  (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+typedef struct
+{
+  /* Version of flags structure.  */
+  Elf32_Half version;
+  /* The level of the ISA: 1-5, 32, 64.  */
+  unsigned char isa_level;
+  /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise.  */
+  unsigned char isa_rev;
+  /* The size of general purpose registers.  */
+  unsigned char gpr_size;
+  /* The size of co-processor 1 registers.  */
+  unsigned char cpr1_size;
+  /* The size of co-processor 2 registers.  */
+  unsigned char cpr2_size;
+  /* The floating-point ABI.  */
+  unsigned char fp_abi;
+  /* Processor-specific extension.  */
+  Elf32_Word isa_ext;
+  /* Mask of ASEs used.  */
+  Elf32_Word ases;
+  /* Mask of general flags.  */
+  Elf32_Word flags1;
+  Elf32_Word flags2;
+} Elf_MIPS_ABIFlags_v0;
+
+/* Values for the register size bytes of an abi flags structure.  */
+
+#define MIPS_AFL_REG_NONE	0x00	 /* No registers.  */
+#define MIPS_AFL_REG_32		0x01	 /* 32-bit registers.  */
+#define MIPS_AFL_REG_64		0x02	 /* 64-bit registers.  */
+#define MIPS_AFL_REG_128	0x03	 /* 128-bit registers.  */
+
+/* Masks for the ases word of an ABI flags structure.  */
+
+#define MIPS_AFL_ASE_DSP	0x00000001 /* DSP ASE.  */
+#define MIPS_AFL_ASE_DSPR2	0x00000002 /* DSP R2 ASE.  */
+#define MIPS_AFL_ASE_EVA	0x00000004 /* Enhanced VA Scheme.  */
+#define MIPS_AFL_ASE_MCU	0x00000008 /* MCU (MicroController) ASE.  */
+#define MIPS_AFL_ASE_MDMX	0x00000010 /* MDMX ASE.  */
+#define MIPS_AFL_ASE_MIPS3D	0x00000020 /* MIPS-3D ASE.  */
+#define MIPS_AFL_ASE_MT		0x00000040 /* MT ASE.  */
+#define MIPS_AFL_ASE_SMARTMIPS	0x00000080 /* SmartMIPS ASE.  */
+#define MIPS_AFL_ASE_VIRT	0x00000100 /* VZ ASE.  */
+#define MIPS_AFL_ASE_MSA	0x00000200 /* MSA ASE.  */
+#define MIPS_AFL_ASE_MIPS16	0x00000400 /* MIPS16 ASE.  */
+#define MIPS_AFL_ASE_MICROMIPS	0x00000800 /* MICROMIPS ASE.  */
+#define MIPS_AFL_ASE_XPA	0x00001000 /* XPA ASE.  */
+#define MIPS_AFL_ASE_MASK	0x00001fff /* All ASEs.  */
+
+/* Values for the isa_ext word of an ABI flags structure.  */
+
+#define MIPS_AFL_EXT_XLR	  1   /* RMI Xlr instruction.  */
+#define MIPS_AFL_EXT_OCTEON2	  2   /* Cavium Networks Octeon2.  */
+#define MIPS_AFL_EXT_OCTEONP	  3   /* Cavium Networks OcteonP.  */
+#define MIPS_AFL_EXT_LOONGSON_3A  4   /* Loongson 3A.  */
+#define MIPS_AFL_EXT_OCTEON	  5   /* Cavium Networks Octeon.  */
+#define MIPS_AFL_EXT_5900	  6   /* MIPS R5900 instruction.  */
+#define MIPS_AFL_EXT_4650	  7   /* MIPS R4650 instruction.  */
+#define MIPS_AFL_EXT_4010	  8   /* LSI R4010 instruction.  */
+#define MIPS_AFL_EXT_4100	  9   /* NEC VR4100 instruction.  */
+#define MIPS_AFL_EXT_3900	  10  /* Toshiba R3900 instruction.  */
+#define MIPS_AFL_EXT_10000	  11  /* MIPS R10000 instruction.  */
+#define MIPS_AFL_EXT_SB1	  12  /* Broadcom SB-1 instruction.  */
+#define MIPS_AFL_EXT_4111	  13  /* NEC VR4111/VR4181 instruction.  */
+#define MIPS_AFL_EXT_4120	  14  /* NEC VR4120 instruction.  */
+#define MIPS_AFL_EXT_5400	  15  /* NEC VR5400 instruction.  */
+#define MIPS_AFL_EXT_5500	  16  /* NEC VR5500 instruction.  */
+#define MIPS_AFL_EXT_LOONGSON_2E  17  /* ST Microelectronics Loongson 2E.  */
+#define MIPS_AFL_EXT_LOONGSON_2F  18  /* ST Microelectronics Loongson 2F.  */
+
+/* Masks for the flags1 word of an ABI flags structure.  */
+#define MIPS_AFL_FLAGS1_ODDSPREG  1  /* Uses odd single-precision registers.  */
+
+/* Object attribute values.  */
+enum
+{
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_MIPS_ABI_FP_ANY = 0,
+  /* Using hard-float -mdouble-float.  */
+  Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+  /* Using hard-float -msingle-float.  */
+  Val_GNU_MIPS_ABI_FP_SINGLE = 2,
+  /* Using soft-float.  */
+  Val_GNU_MIPS_ABI_FP_SOFT = 3,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
+  /* Using -mfpxx.  */
+  Val_GNU_MIPS_ABI_FP_XX = 5,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_64 = 6,
+  /* Using -mips32r2 -mfp64 -mno-odd-spreg.  */
+  Val_GNU_MIPS_ABI_FP_64A = 7,
+  /* Maximum allocated FP ABI value.  */
+  Val_GNU_MIPS_ABI_FP_MAX = 7
+};
+
+/* HPPA specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_PARISC_TRAPNIL	0x00010000 /* Trap nil pointer dereference.  */
+#define EF_PARISC_EXT		0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB		0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE		0x00080000 /* Program expects wide mode.  */
+#define EF_PARISC_NO_KABP	0x00100000 /* No kernel assisted branch
+					      prediction.  */
+#define EF_PARISC_LAZYSWAP	0x00400000 /* Allow lazy swapping.  */
+#define EF_PARISC_ARCH		0x0000ffff /* Architecture version.  */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */
+
+#define EFA_PARISC_1_0		    0x020b /* PA-RISC 1.0 big-endian.  */
+#define EFA_PARISC_1_1		    0x0210 /* PA-RISC 1.1 big-endian.  */
+#define EFA_PARISC_2_0		    0x0214 /* PA-RISC 2.0 big-endian.  */
+
+/* Additional section indeces.  */
+
+#define SHN_PARISC_ANSI_COMMON	0xff00	   /* Section for tenatively declared
+					      symbols in ANSI C.  */
+#define SHN_PARISC_HUGE_COMMON	0xff01	   /* Common blocks in huge model.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_EXT		0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND	0x70000001 /* Unwind information.  */
+#define SHT_PARISC_DOC		0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT	0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE		0x40000000 /* Section far from gp.  */
+#define SHF_PARISC_SBP		0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE	13	/* Millicode function entry point.  */
+
+#define STT_HP_OPAQUE		(STT_LOOS + 0x1)
+#define STT_HP_STUB		(STT_LOOS + 0x2)
+
+/* HPPA relocs.  */
+
+#define R_PARISC_NONE		0	/* No reloc.  */
+#define R_PARISC_DIR32		1	/* Direct 32-bit reference.  */
+#define R_PARISC_DIR21L		2	/* Left 21 bits of eff. address.  */
+#define R_PARISC_DIR17R		3	/* Right 17 bits of eff. address.  */
+#define R_PARISC_DIR17F		4	/* 17 bits of eff. address.  */
+#define R_PARISC_DIR14R		6	/* Right 14 bits of eff. address.  */
+#define R_PARISC_PCREL32	9	/* 32-bit rel. address.  */
+#define R_PARISC_PCREL21L	10	/* Left 21 bits of rel. address.  */
+#define R_PARISC_PCREL17R	11	/* Right 17 bits of rel. address.  */
+#define R_PARISC_PCREL17F	12	/* 17 bits of rel. address.  */
+#define R_PARISC_PCREL14R	14	/* Right 14 bits of rel. address.  */
+#define R_PARISC_DPREL21L	18	/* Left 21 bits of rel. address.  */
+#define R_PARISC_DPREL14R	22	/* Right 14 bits of rel. address.  */
+#define R_PARISC_GPREL21L	26	/* GP-relative, left 21 bits.  */
+#define R_PARISC_GPREL14R	30	/* GP-relative, right 14 bits.  */
+#define R_PARISC_LTOFF21L	34	/* LT-relative, left 21 bits.  */
+#define R_PARISC_LTOFF14R	38	/* LT-relative, right 14 bits.  */
+#define R_PARISC_SECREL32	41	/* 32 bits section rel. address.  */
+#define R_PARISC_SEGBASE	48	/* No relocation, set segment base.  */
+#define R_PARISC_SEGREL32	49	/* 32 bits segment rel. address.  */
+#define R_PARISC_PLTOFF21L	50	/* PLT rel. address, left 21 bits.  */
+#define R_PARISC_PLTOFF14R	54	/* PLT rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_FPTR32	57	/* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L	58	/* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R	62	/* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64		64	/* 64 bits function address.  */
+#define R_PARISC_PLABEL32	65	/* 32 bits function address.  */
+#define R_PARISC_PLABEL21L	66	/* Left 21 bits of fdesc address.  */
+#define R_PARISC_PLABEL14R	70	/* Right 14 bits of fdesc address.  */
+#define R_PARISC_PCREL64	72	/* 64 bits PC-rel. address.  */
+#define R_PARISC_PCREL22F	74	/* 22 bits PC-rel. address.  */
+#define R_PARISC_PCREL14WR	75	/* PC-rel. address, right 14 bits.  */
+#define R_PARISC_PCREL14DR	76	/* PC rel. address, right 14 bits.  */
+#define R_PARISC_PCREL16F	77	/* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16WF	78	/* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16DF	79	/* 16 bits PC-rel. address.  */
+#define R_PARISC_DIR64		80	/* 64 bits of eff. address.  */
+#define R_PARISC_DIR14WR	83	/* 14 bits of eff. address.  */
+#define R_PARISC_DIR14DR	84	/* 14 bits of eff. address.  */
+#define R_PARISC_DIR16F		85	/* 16 bits of eff. address.  */
+#define R_PARISC_DIR16WF	86	/* 16 bits of eff. address.  */
+#define R_PARISC_DIR16DF	87	/* 16 bits of eff. address.  */
+#define R_PARISC_GPREL64	88	/* 64 bits of GP-rel. address.  */
+#define R_PARISC_GPREL14WR	91	/* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL14DR	92	/* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL16F	93	/* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16WF	94	/* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16DF	95	/* 16 bits GP-rel. address.  */
+#define R_PARISC_LTOFF64	96	/* 64 bits LT-rel. address.  */
+#define R_PARISC_LTOFF14WR	99	/* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF14DR	100	/* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF16F	101	/* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16WF	102	/* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16DF	103	/* 16 bits LT-rel. address.  */
+#define R_PARISC_SECREL64	104	/* 64 bits section rel. address.  */
+#define R_PARISC_SEGREL64	112	/* 64 bits segment rel. address.  */
+#define R_PARISC_PLTOFF14WR	115	/* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF14DR	116	/* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF16F	117	/* 16 bits LT-rel. address.  */
+#define R_PARISC_PLTOFF16WF	118	/* 16 bits PLT-rel. address.  */
+#define R_PARISC_PLTOFF16DF	119	/* 16 bits PLT-rel. address.  */
+#define R_PARISC_LTOFF_FPTR64	120	/* 64 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR14WR	123	/* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR	124	/* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F	125	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16WF	126	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16DF	127	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LORESERVE	128
+#define R_PARISC_COPY		128	/* Copy relocation.  */
+#define R_PARISC_IPLT		129	/* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT		130	/* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32	153	/* 32 bits TP-rel. address.  */
+#define R_PARISC_TPREL21L	154	/* TP-rel. address, left 21 bits.  */
+#define R_PARISC_TPREL14R	158	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_TP21L	162	/* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R	166	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F	167	/* 14 bits LT-TP-rel. address.  */
+#define R_PARISC_TPREL64	216	/* 64 bits TP-rel. address.  */
+#define R_PARISC_TPREL14WR	219	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL14DR	220	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL16F	221	/* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16WF	222	/* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16DF	223	/* 16 bits TP-rel. address.  */
+#define R_PARISC_LTOFF_TP64	224	/* 64 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP14WR	227	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR	228	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F	229	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16WF	230	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16DF	231	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_GNU_VTENTRY	232
+#define R_PARISC_GNU_VTINHERIT	233
+#define R_PARISC_TLS_GD21L	234	/* GD 21-bit left.  */
+#define R_PARISC_TLS_GD14R	235	/* GD 14-bit right.  */
+#define R_PARISC_TLS_GDCALL	236	/* GD call to __t_g_a.  */
+#define R_PARISC_TLS_LDM21L	237	/* LD module 21-bit left.  */
+#define R_PARISC_TLS_LDM14R	238	/* LD module 14-bit right.  */
+#define R_PARISC_TLS_LDMCALL	239	/* LD module call to __t_g_a.  */
+#define R_PARISC_TLS_LDO21L	240	/* LD offset 21-bit left.  */
+#define R_PARISC_TLS_LDO14R	241	/* LD offset 14-bit right.  */
+#define R_PARISC_TLS_DTPMOD32	242	/* DTP module 32-bit.  */
+#define R_PARISC_TLS_DTPMOD64	243	/* DTP module 64-bit.  */
+#define R_PARISC_TLS_DTPOFF32	244	/* DTP offset 32-bit.  */
+#define R_PARISC_TLS_DTPOFF64	245	/* DTP offset 32-bit.  */
+#define R_PARISC_TLS_LE21L	R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R	R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L	R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R	R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32	R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64	R_PARISC_TPREL64
+#define R_PARISC_HIRESERVE	255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PT_HP_TLS		(PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE		(PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION	(PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL	(PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM		(PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC		(PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE	(PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK	(PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM		(PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF		(PT_LOOS + 0x9)
+#define PT_HP_PARALLEL		(PT_LOOS + 0x10)
+#define PT_HP_FASTBIND		(PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT		(PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT		(PT_LOOS + 0x13)
+#define PT_HP_STACK		(PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT	0x70000000
+#define PT_PARISC_UNWIND	0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PF_PARISC_SBP		0x08000000
+
+#define PF_HP_PAGE_SIZE		0x00100000
+#define PF_HP_FAR_SHARED	0x00200000
+#define PF_HP_NEAR_SHARED	0x00400000
+#define PF_HP_CODE		0x01000000
+#define PF_HP_MODIFY		0x02000000
+#define PF_HP_LAZYSWAP		0x04000000
+#define PF_HP_SBP		0x08000000
+
+
+/* Alpha specific definitions.  */
+
+/* Legal values for e_flags field of Elf64_Ehdr.  */
+
+#define EF_ALPHA_32BIT		1	/* All addresses must be < 2GB.  */
+#define EF_ALPHA_CANRELAX	2	/* Relocations for relaxing exist.  */
+
+/* Legal values for sh_type field of Elf64_Shdr.  */
+
+/* These two are primerily concerned with ECOFF debugging info.  */
+#define SHT_ALPHA_DEBUG		0x70000001
+#define SHT_ALPHA_REGINFO	0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr.  */
+
+#define SHF_ALPHA_GPREL		0x10000000
+
+/* Legal values for st_other field of Elf64_Sym.  */
+#define STO_ALPHA_NOPV		0x80	/* No PV required.  */
+#define STO_ALPHA_STD_GPLOAD	0x88	/* PV only used for initial ldgp.  */
+
+/* Alpha relocs.  */
+
+#define R_ALPHA_NONE		0	/* No reloc */
+#define R_ALPHA_REFLONG		1	/* Direct 32 bit */
+#define R_ALPHA_REFQUAD		2	/* Direct 64 bit */
+#define R_ALPHA_GPREL32		3	/* GP relative 32 bit */
+#define R_ALPHA_LITERAL		4	/* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE		5	/* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP		6	/* Add displacement to GP */
+#define R_ALPHA_BRADDR		7	/* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT		8	/* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16		9	/* PC relative 16 bit */
+#define R_ALPHA_SREL32		10	/* PC relative 32 bit */
+#define R_ALPHA_SREL64		11	/* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH	17	/* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW	18	/* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16		19	/* GP relative 16 bit */
+#define R_ALPHA_COPY		24	/* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT	25	/* Create GOT entry */
+#define R_ALPHA_JMP_SLOT	26	/* Create PLT entry */
+#define R_ALPHA_RELATIVE	27	/* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI	28
+#define R_ALPHA_TLSGD		29
+#define R_ALPHA_TLS_LDM		30
+#define R_ALPHA_DTPMOD64	31
+#define R_ALPHA_GOTDTPREL	32
+#define R_ALPHA_DTPREL64	33
+#define R_ALPHA_DTPRELHI	34
+#define R_ALPHA_DTPRELLO	35
+#define R_ALPHA_DTPREL16	36
+#define R_ALPHA_GOTTPREL	37
+#define R_ALPHA_TPREL64		38
+#define R_ALPHA_TPRELHI		39
+#define R_ALPHA_TPRELLO		40
+#define R_ALPHA_TPREL16		41
+/* Keep this the last entry.  */
+#define R_ALPHA_NUM		46
+
+/* Magic values of the LITUSE relocation addend.  */
+#define LITUSE_ALPHA_ADDR	0
+#define LITUSE_ALPHA_BASE	1
+#define LITUSE_ALPHA_BYTOFF	2
+#define LITUSE_ALPHA_JSR	3
+#define LITUSE_ALPHA_TLS_GD	4
+#define LITUSE_ALPHA_TLS_LDM	5
+
+/* Legal values for d_tag of Elf64_Dyn.  */
+#define DT_ALPHA_PLTRO		(DT_LOPROC + 0)
+#define DT_ALPHA_NUM		1
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags.  */
+#define EF_PPC_EMB		0x80000000	/* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE	0x00010000	/* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB	0x00008000	/* PowerPC -mrelocatable-lib
+						   flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE		0
+#define R_PPC_ADDR32		1	/* 32bit absolute address */
+#define R_PPC_ADDR24		2	/* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16		3	/* 16bit absolute address */
+#define R_PPC_ADDR16_LO		4	/* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI		5	/* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA		6	/* adjusted high 16bit */
+#define R_PPC_ADDR14		7	/* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN	8
+#define R_PPC_ADDR14_BRNTAKEN	9
+#define R_PPC_REL24		10	/* PC relative 26 bit */
+#define R_PPC_REL14		11	/* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN	12
+#define R_PPC_REL14_BRNTAKEN	13
+#define R_PPC_GOT16		14
+#define R_PPC_GOT16_LO		15
+#define R_PPC_GOT16_HI		16
+#define R_PPC_GOT16_HA		17
+#define R_PPC_PLTREL24		18
+#define R_PPC_COPY		19
+#define R_PPC_GLOB_DAT		20
+#define R_PPC_JMP_SLOT		21
+#define R_PPC_RELATIVE		22
+#define R_PPC_LOCAL24PC		23
+#define R_PPC_UADDR32		24
+#define R_PPC_UADDR16		25
+#define R_PPC_REL32		26
+#define R_PPC_PLT32		27
+#define R_PPC_PLTREL32		28
+#define R_PPC_PLT16_LO		29
+#define R_PPC_PLT16_HI		30
+#define R_PPC_PLT16_HA		31
+#define R_PPC_SDAREL16		32
+#define R_PPC_SECTOFF		33
+#define R_PPC_SECTOFF_LO	34
+#define R_PPC_SECTOFF_HI	35
+#define R_PPC_SECTOFF_HA	36
+
+/* PowerPC relocations defined for the TLS access ABI.  */
+#define R_PPC_TLS		67 /* none	(sym+add)@tls */
+#define R_PPC_DTPMOD32		68 /* word32	(sym+add)@dtpmod */
+#define R_PPC_TPREL16		69 /* half16*	(sym+add)@tprel */
+#define R_PPC_TPREL16_LO	70 /* half16	(sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI	71 /* half16	(sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA	72 /* half16	(sym+add)@tprel@ha */
+#define R_PPC_TPREL32		73 /* word32	(sym+add)@tprel */
+#define R_PPC_DTPREL16		74 /* half16*	(sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO	75 /* half16	(sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI	76 /* half16	(sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA	77 /* half16	(sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32		78 /* word32	(sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16	79 /* half16*	(sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO	80 /* half16	(sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI	81 /* half16	(sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA	82 /* half16	(sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16	83 /* half16*	(sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO	84 /* half16	(sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI	85 /* half16	(sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA	86 /* half16	(sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16	87 /* half16*	(sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO	88 /* half16	(sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI	89 /* half16	(sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA	90 /* half16	(sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16	91 /* half16*	(sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO	92 /* half16*	(sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI	93 /* half16*	(sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA	94 /* half16*	(sym+add)@got@dtprel@ha */
+#define R_PPC_TLSGD		95 /* none	(sym+add)@tlsgd */
+#define R_PPC_TLSLD		96 /* none	(sym+add)@tlsld */
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+   in the SVR4 ELF ABI.  */
+#define R_PPC_EMB_NADDR32	101
+#define R_PPC_EMB_NADDR16	102
+#define R_PPC_EMB_NADDR16_LO	103
+#define R_PPC_EMB_NADDR16_HI	104
+#define R_PPC_EMB_NADDR16_HA	105
+#define R_PPC_EMB_SDAI16	106
+#define R_PPC_EMB_SDA2I16	107
+#define R_PPC_EMB_SDA2REL	108
+#define R_PPC_EMB_SDA21		109	/* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF	110
+#define R_PPC_EMB_RELSEC16	111
+#define R_PPC_EMB_RELST_LO	112
+#define R_PPC_EMB_RELST_HI	113
+#define R_PPC_EMB_RELST_HA	114
+#define R_PPC_EMB_BIT_FLD	115
+#define R_PPC_EMB_RELSDA	116	/* 16 bit relative offset in SDA */
+
+/* Diab tool relocations.  */
+#define R_PPC_DIAB_SDA21_LO	180	/* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI	181	/* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA	182	/* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO	183	/* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI	184	/* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA	185	/* like EMB_RELSDA, adjusted high 16 */
+
+/* GNU extension to support local ifunc.  */
+#define R_PPC_IRELATIVE		248
+
+/* GNU relocs used in PIC code sequences.  */
+#define R_PPC_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC_REL16_LO		250	/* half16   (sym+add-.)@l */
+#define R_PPC_REL16_HI		251	/* half16   (sym+add-.)@h */
+#define R_PPC_REL16_HA		252	/* half16   (sym+add-.)@ha */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+   that may still be in object files.  */
+#define R_PPC_TOC16		255
+
+/* PowerPC specific values for the Dyn d_tag field.  */
+#define DT_PPC_GOT		(DT_LOPROC + 0)
+#define DT_PPC_OPT		(DT_LOPROC + 1)
+#define DT_PPC_NUM		2
+
+/* PowerPC specific values for the DT_PPC_OPT Dyn entry.  */
+#define PPC_OPT_TLS		1
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE		R_PPC_NONE
+#define R_PPC64_ADDR32		R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24		R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16		R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO	R_PPC_ADDR16_LO	/* lower 16bits of address */
+#define R_PPC64_ADDR16_HI	R_PPC_ADDR16_HI	/* high 16bits of address. */
+#define R_PPC64_ADDR16_HA	R_PPC_ADDR16_HA /* adjusted high 16bits.  */
+#define R_PPC64_ADDR14		R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN	R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN	R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24		R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14		R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN	R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN	R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16		R_PPC_GOT16
+#define R_PPC64_GOT16_LO	R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI	R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA	R_PPC_GOT16_HA
+
+#define R_PPC64_COPY		R_PPC_COPY
+#define R_PPC64_GLOB_DAT	R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT	R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE	R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32		R_PPC_UADDR32
+#define R_PPC64_UADDR16		R_PPC_UADDR16
+#define R_PPC64_REL32		R_PPC_REL32
+#define R_PPC64_PLT32		R_PPC_PLT32
+#define R_PPC64_PLTREL32	R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO	R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI	R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA	R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF		R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO	R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI	R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA	R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30		37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64		38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER	39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA	40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST	41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA	42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64		43 /* doubleword64 S + A */
+#define R_PPC64_REL64		44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64		45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64	46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16		47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO	48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI	49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA	50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC		51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16	52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO	53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI	54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA	55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS	56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS	57 /* half16ds  #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS	58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS	59 /* half16ds  #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS	60 /* half16ds  #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS	61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS	62 /* half16ds  #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS	63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS	64 /* half16ds  #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS	65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS	66 /* half16ds  #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI.  */
+#define R_PPC64_TLS		67 /* none	(sym+add)@tls */
+#define R_PPC64_DTPMOD64	68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16		69 /* half16*	(sym+add)@tprel */
+#define R_PPC64_TPREL16_LO	70 /* half16	(sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI	71 /* half16	(sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA	72 /* half16	(sym+add)@tprel@ha */
+#define R_PPC64_TPREL64		73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16	74 /* half16*	(sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO	75 /* half16	(sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI	76 /* half16	(sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA	77 /* half16	(sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64	78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16	79 /* half16*	(sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO	80 /* half16	(sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI	81 /* half16	(sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA	82 /* half16	(sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16	83 /* half16*	(sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO	84 /* half16	(sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI	85 /* half16	(sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA	86 /* half16	(sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS	87 /* half16ds*	(sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI	89 /* half16	(sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA	90 /* half16	(sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS	91 /* half16ds*	(sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI	93 /* half16	(sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA	94 /* half16	(sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS	95 /* half16ds*	(sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS	96 /* half16ds	(sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER	97 /* half16	(sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA	98 /* half16	(sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST	99 /* half16	(sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16	(sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS	101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS	102 /* half16ds	(sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER	103 /* half16	(sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16	(sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16	(sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16	(sym+add)@dtprel@highesta */
+#define R_PPC64_TLSGD		107 /* none	(sym+add)@tlsgd */
+#define R_PPC64_TLSLD		108 /* none	(sym+add)@tlsld */
+#define R_PPC64_TOCSAVE		109 /* none */
+
+/* Added when HA and HI relocs were changed to report overflows.  */
+#define R_PPC64_ADDR16_HIGH	110
+#define R_PPC64_ADDR16_HIGHA	111
+#define R_PPC64_TPREL16_HIGH	112
+#define R_PPC64_TPREL16_HIGHA	113
+#define R_PPC64_DTPREL16_HIGH	114
+#define R_PPC64_DTPREL16_HIGHA	115
+
+/* GNU extension to support local ifunc.  */
+#define R_PPC64_JMP_IREL	247
+#define R_PPC64_IRELATIVE	248
+#define R_PPC64_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC64_REL16_LO	250	/* half16   (sym+add-.)@l */
+#define R_PPC64_REL16_HI	251	/* half16   (sym+add-.)@h */
+#define R_PPC64_REL16_HA	252	/* half16   (sym+add-.)@ha */
+
+/* e_flags bits specifying ABI.
+   1 for original function descriptor using ABI,
+   2 for revised ABI without function descriptors,
+   0 for unspecified or not using any features affected by the differences.  */
+#define EF_PPC64_ABI	3
+
+/* PowerPC64 specific values for the Dyn d_tag field.  */
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_OPD	(DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ	(DT_LOPROC + 2)
+#define DT_PPC64_OPT	(DT_LOPROC + 3)
+#define DT_PPC64_NUM    4
+
+/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry.  */
+#define PPC64_OPT_TLS		1
+#define PPC64_OPT_MULTI_TOC	2
+
+/* PowerPC64 specific values for the Elf64_Sym st_other field.  */
+#define STO_PPC64_LOCAL_BIT	5
+#define STO_PPC64_LOCAL_MASK	(7 << STO_PPC64_LOCAL_BIT)
+#define PPC64_LOCAL_ENTRY_OFFSET(other)				\
+ (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
+
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_ARM_RELEXEC		0x01
+#define EF_ARM_HASENTRY		0x02
+#define EF_ARM_INTERWORK	0x04
+#define EF_ARM_APCS_26		0x08
+#define EF_ARM_APCS_FLOAT	0x10
+#define EF_ARM_PIC		0x20
+#define EF_ARM_ALIGN8		0x40 /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI		0x80
+#define EF_ARM_OLD_ABI		0x100
+#define EF_ARM_SOFT_FLOAT	0x200
+#define EF_ARM_VFP_FLOAT	0x400
+#define EF_ARM_MAVERICK_FLOAT	0x800
+
+#define EF_ARM_ABI_FLOAT_SOFT	0x200   /* NB conflicts with EF_ARM_SOFT_FLOAT */
+#define EF_ARM_ABI_FLOAT_HARD	0x400   /* NB conflicts with EF_ARM_VFP_FLOAT */
+
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+/* NB. These conflict with values defined above.  */
+#define EF_ARM_SYMSARESORTED	0x04
+#define EF_ARM_DYNSYMSUSESEGIDX	0x08
+#define EF_ARM_MAPSYMSFIRST	0x10
+#define EF_ARM_EABIMASK		0XFF000000
+
+/* Constants defined in AAELF.  */
+#define EF_ARM_BE8	    0x00800000
+#define EF_ARM_LE8	    0x00400000
+
+#define EF_ARM_EABI_VERSION(flags)	((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN	0x00000000
+#define EF_ARM_EABI_VER1	0x01000000
+#define EF_ARM_EABI_VER2	0x02000000
+#define EF_ARM_EABI_VER3	0x03000000
+#define EF_ARM_EABI_VER4	0x04000000
+#define EF_ARM_EABI_VER5	0x05000000
+
+/* Additional symbol types for Thumb.  */
+#define STT_ARM_TFUNC		STT_LOPROC /* A Thumb function.  */
+#define STT_ARM_16BIT		STT_HIPROC /* A Thumb label.  */
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT	0x10000000 /* Section contains an entry point */
+#define SHF_ARM_COMDEF		0x80000000 /* Section may be multiply defined
+					      in the input to a link step.  */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB		0x10000000 /* Segment contains the location
+					      addressed by the static base. */
+#define PF_ARM_PI		0x20000000 /* Position-independent segment.  */
+#define PF_ARM_ABS		0x40000000 /* Absolute segment.  */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_ARM_EXIDX		(PT_LOPROC + 1)	/* ARM unwind segment.  */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_ARM_EXIDX		(SHT_LOPROC + 1) /* ARM unwind section.  */
+#define SHT_ARM_PREEMPTMAP	(SHT_LOPROC + 2) /* Preemption details.  */
+#define SHT_ARM_ATTRIBUTES	(SHT_LOPROC + 3) /* ARM attributes section.  */
+
+
+/* AArch64 relocs.  */
+
+#define R_AARCH64_NONE            0	/* No relocation.  */
+
+/* ILP32 AArch64 relocs.  */
+#define R_AARCH64_P32_ABS32		  1	/* Direct 32 bit.  */
+#define R_AARCH64_P32_COPY		180	/* Copy symbol at runtime.  */
+#define R_AARCH64_P32_GLOB_DAT		181	/* Create GOT entry.  */
+#define R_AARCH64_P32_JUMP_SLOT		182	/* Create PLT entry.  */
+#define R_AARCH64_P32_RELATIVE		183	/* Adjust by program base.  */
+#define R_AARCH64_P32_TLS_DTPMOD	184	/* Module number, 32 bit.  */
+#define R_AARCH64_P32_TLS_DTPREL	185	/* Module-relative offset, 32 bit.  */
+#define R_AARCH64_P32_TLS_TPREL		186	/* TP-relative offset, 32 bit.  */
+#define R_AARCH64_P32_TLSDESC		187	/* TLS Descriptor.  */
+#define R_AARCH64_P32_IRELATIVE		188	/* STT_GNU_IFUNC relocation. */
+
+/* LP64 AArch64 relocs.  */
+#define R_AARCH64_ABS64         257	/* Direct 64 bit. */
+#define R_AARCH64_ABS32         258	/* Direct 32 bit.  */
+#define R_AARCH64_ABS16		259	/* Direct 16-bit.  */
+#define R_AARCH64_PREL64	260	/* PC-relative 64-bit.	*/
+#define R_AARCH64_PREL32	261	/* PC-relative 32-bit.	*/
+#define R_AARCH64_PREL16	262	/* PC-relative 16-bit.	*/
+#define R_AARCH64_MOVW_UABS_G0	263	/* Dir. MOVZ imm. from bits 15:0.  */
+#define R_AARCH64_MOVW_UABS_G0_NC 264	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G1	265	/* Dir. MOVZ imm. from bits 31:16.  */
+#define R_AARCH64_MOVW_UABS_G1_NC 266	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G2	267	/* Dir. MOVZ imm. from bits 47:32.  */
+#define R_AARCH64_MOVW_UABS_G2_NC 268	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G3	269	/* Dir. MOV{K,Z} imm. from 63:48.  */
+#define R_AARCH64_MOVW_SABS_G0	270	/* Dir. MOV{N,Z} imm. from 15:0.  */
+#define R_AARCH64_MOVW_SABS_G1	271	/* Dir. MOV{N,Z} imm. from 31:16.  */
+#define R_AARCH64_MOVW_SABS_G2	272	/* Dir. MOV{N,Z} imm. from 47:32.  */
+#define R_AARCH64_LD_PREL_LO19	273	/* PC-rel. LD imm. from bits 20:2.  */
+#define R_AARCH64_ADR_PREL_LO21	274	/* PC-rel. ADR imm. from bits 20:0.  */
+#define R_AARCH64_ADR_PREL_PG_HI21 275	/* Page-rel. ADRP imm. from 32:12.  */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check.  */
+#define R_AARCH64_ADD_ABS_LO12_NC 277	/* Dir. ADD imm. from bits 11:0.  */
+#define R_AARCH64_LDST8_ABS_LO12_NC 278	/* Likewise for LD/ST; no check. */
+#define R_AARCH64_TSTBR14	279	/* PC-rel. TBZ/TBNZ imm. from 15:2.  */
+#define R_AARCH64_CONDBR19	280	/* PC-rel. cond. br. imm. from 20:2. */
+#define R_AARCH64_JUMP26	282	/* PC-rel. B imm. from bits 27:2.  */
+#define R_AARCH64_CALL26	283	/* Likewise for CALL.  */
+#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1.  */
+#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2.  */
+#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3.  */
+#define R_AARCH64_MOVW_PREL_G0	287	/* PC-rel. MOV{N,Z} imm. from 15:0.  */
+#define R_AARCH64_MOVW_PREL_G0_NC 288	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G1	289	/* PC-rel. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_PREL_G1_NC 290	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G2	291	/* PC-rel. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_MOVW_PREL_G2_NC 292	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G3	293	/* PC-rel. MOV{N,Z} imm. from 63:48. */
+#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4.  */
+#define R_AARCH64_MOVW_GOTOFF_G0 300	/* GOT-rel. off. MOV{N,Z} imm. 15:0. */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G1 302	/* GOT-rel. o. MOV{N,Z} imm. 31:16.  */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G2 304	/* GOT-rel. o. MOV{N,Z} imm. 47:32.  */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G3 306	/* GOT-rel. o. MOV{N,Z} imm. 63:48.  */
+#define R_AARCH64_GOTREL64	307	/* GOT-relative 64-bit.  */
+#define R_AARCH64_GOTREL32	308	/* GOT-relative 32-bit.  */
+#define R_AARCH64_GOT_LD_PREL19	309	/* PC-rel. GOT off. load imm. 20:2.  */
+#define R_AARCH64_LD64_GOTOFF_LO15 310	/* GOT-rel. off. LD/ST imm. 14:3.  */
+#define R_AARCH64_ADR_GOT_PAGE	311	/* P-page-rel. GOT off. ADRP 32:12.  */
+#define R_AARCH64_LD64_GOT_LO12_NC 312	/* Dir. GOT off. LD/ST imm. 11:3.  */
+#define R_AARCH64_LD64_GOTPAGE_LO15 313	/* GOT-page-rel. GOT off. LD/ST 14:3 */
+#define R_AARCH64_TLSGD_ADR_PREL21 512	/* PC-relative ADR imm. 20:0.  */
+#define R_AARCH64_TLSGD_ADR_PAGE21 513	/* page-rel. ADRP imm. 32:12.  */
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514	/* direct ADD imm. from 11:0.  */
+#define R_AARCH64_TLSGD_MOVW_G1	515	/* GOT-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516	/* GOT-rel. MOVK imm. 15:0.  */
+#define R_AARCH64_TLSLD_ADR_PREL21 517	/* Like 512; local dynamic model.  */
+#define R_AARCH64_TLSLD_ADR_PAGE21 518	/* Like 513; local dynamic model.  */
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519	/* Like 514; local dynamic model.  */
+#define R_AARCH64_TLSLD_MOVW_G1	520	/* Like 515; local dynamic model.  */
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521	/* Like 516; local dynamic model.  */
+#define R_AARCH64_TLSLD_LD_PREL19 522	/* TLS PC-rel. load imm. 20:2.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0.  */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check.  */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0.  */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1.  */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2.  */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3.  */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check.  */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0.  */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12.  */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3.  */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check.  */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0.  */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1.  */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check.  */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2.  */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check.  */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3.  */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check.  */
+#define R_AARCH64_TLSDESC_LD_PREL19 560	/* PC-rel. load immediate 20:2.  */
+#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0.  */
+#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12.  */
+#define R_AARCH64_TLSDESC_LD64_LO12 563	/* Direct LD off. from 11:3.  */
+#define R_AARCH64_TLSDESC_ADD_LO12 564	/* Direct ADD imm. from 11:0.  */
+#define R_AARCH64_TLSDESC_OFF_G1 565	/* GOT-rel. MOV{N,Z} imm. 31:16.  */
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566	/* GOT-rel. MOVK imm. 15:0; no ck.  */
+#define R_AARCH64_TLSDESC_LDR	567	/* Relax LDR.  */
+#define R_AARCH64_TLSDESC_ADD	568	/* Relax ADD.  */
+#define R_AARCH64_TLSDESC_CALL	569	/* Relax BLR.  */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4.  */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check.  */
+#define R_AARCH64_COPY         1024	/* Copy symbol at runtime.  */
+#define R_AARCH64_GLOB_DAT     1025	/* Create GOT entry.  */
+#define R_AARCH64_JUMP_SLOT    1026	/* Create PLT entry.  */
+#define R_AARCH64_RELATIVE     1027	/* Adjust by program base.  */
+#define R_AARCH64_TLS_DTPMOD   1028	/* Module number, 64 bit.  */
+#define R_AARCH64_TLS_DTPREL   1029	/* Module-relative offset, 64 bit.  */
+#define R_AARCH64_TLS_TPREL    1030	/* TP-relative offset, 64 bit.  */
+#define R_AARCH64_TLSDESC      1031	/* TLS Descriptor.  */
+#define R_AARCH64_IRELATIVE	1032	/* STT_GNU_IFUNC relocation.  */
+
+/* ARM relocs.  */
+
+#define R_ARM_NONE		0	/* No reloc */
+#define R_ARM_PC24		1	/* Deprecated PC relative 26
+					   bit branch.  */
+#define R_ARM_ABS32		2	/* Direct 32 bit  */
+#define R_ARM_REL32		3	/* PC relative 32 bit */
+#define R_ARM_PC13		4
+#define R_ARM_ABS16		5	/* Direct 16 bit */
+#define R_ARM_ABS12		6	/* Direct 12 bit */
+#define R_ARM_THM_ABS5		7	/* Direct & 0x7C (LDR, STR).  */
+#define R_ARM_ABS8		8	/* Direct 8 bit */
+#define R_ARM_SBREL32		9
+#define R_ARM_THM_PC22		10	/* PC relative 24 bit (Thumb32 BL).  */
+#define R_ARM_THM_PC8		11	/* PC relative & 0x3FC
+					   (Thumb16 LDR, ADD, ADR).  */
+#define R_ARM_AMP_VCALL9	12
+#define R_ARM_SWI24		13	/* Obsolete static relocation.  */
+#define R_ARM_TLS_DESC		13      /* Dynamic relocation.  */
+#define R_ARM_THM_SWI8		14	/* Reserved.  */
+#define R_ARM_XPC25		15	/* Reserved.  */
+#define R_ARM_THM_XPC22		16	/* Reserved.  */
+#define R_ARM_TLS_DTPMOD32	17	/* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32	18	/* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32	19	/* Offset in static TLS block */
+#define R_ARM_COPY		20	/* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT		21	/* Create GOT entry */
+#define R_ARM_JUMP_SLOT		22	/* Create PLT entry */
+#define R_ARM_RELATIVE		23	/* Adjust by program base */
+#define R_ARM_GOTOFF		24	/* 32 bit offset to GOT */
+#define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32		26	/* 32 bit GOT entry */
+#define R_ARM_PLT32		27	/* Deprecated, 32 bit PLT address.  */
+#define R_ARM_CALL		28	/* PC relative 24 bit (BL, BLX).  */
+#define R_ARM_JUMP24		29	/* PC relative 24 bit
+					   (B, BL<cond>).  */
+#define R_ARM_THM_JUMP24	30	/* PC relative 24 bit (Thumb32 B.W).  */
+#define R_ARM_BASE_ABS		31	/* Adjust by program base.  */
+#define R_ARM_ALU_PCREL_7_0	32	/* Obsolete.  */
+#define R_ARM_ALU_PCREL_15_8	33	/* Obsolete.  */
+#define R_ARM_ALU_PCREL_23_15	34	/* Obsolete.  */
+#define R_ARM_LDR_SBREL_11_0	35	/* Deprecated, prog. base relative.  */
+#define R_ARM_ALU_SBREL_19_12	36	/* Deprecated, prog. base relative.  */
+#define R_ARM_ALU_SBREL_27_20	37	/* Deprecated, prog. base relative.  */
+#define R_ARM_TARGET1		38
+#define R_ARM_SBREL31		39	/* Program base relative.  */
+#define R_ARM_V4BX		40
+#define R_ARM_TARGET2		41
+#define R_ARM_PREL31		42	/* 32 bit PC relative.  */
+#define R_ARM_MOVW_ABS_NC	43	/* Direct 16-bit (MOVW).  */
+#define R_ARM_MOVT_ABS		44	/* Direct high 16-bit (MOVT).  */
+#define R_ARM_MOVW_PREL_NC	45	/* PC relative 16-bit (MOVW).  */
+#define R_ARM_MOVT_PREL		46	/* PC relative (MOVT).  */
+#define R_ARM_THM_MOVW_ABS_NC	47	/* Direct 16 bit (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_ABS	48	/* Direct high 16 bit
+					   (Thumb32 MOVT).  */
+#define R_ARM_THM_MOVW_PREL_NC	49	/* PC relative 16 bit
+					   (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_PREL	50	/* PC relative high 16 bit
+					   (Thumb32 MOVT).  */
+#define R_ARM_THM_JUMP19	51	/* PC relative 20 bit
+					   (Thumb32 B<cond>.W).  */
+#define R_ARM_THM_JUMP6		52	/* PC relative X & 0x7E
+					   (Thumb16 CBZ, CBNZ).  */
+#define R_ARM_THM_ALU_PREL_11_0	53	/* PC relative 12 bit
+					   (Thumb32 ADR.W).  */
+#define R_ARM_THM_PC12		54	/* PC relative 12 bit
+					   (Thumb32 LDR{D,SB,H,SH}).  */
+#define R_ARM_ABS32_NOI		55	/* Direct 32-bit.  */
+#define R_ARM_REL32_NOI		56	/* PC relative 32-bit.  */
+#define R_ARM_ALU_PC_G0_NC	57	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G0		58	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G1_NC	59	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G1		60	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G2		61	/* PC relative (ADD, SUB).  */
+#define R_ARM_LDR_PC_G1		62	/* PC relative (LDR,STR,LDRB,STRB).  */
+#define R_ARM_LDR_PC_G2		63	/* PC relative (LDR,STR,LDRB,STRB).  */
+#define R_ARM_LDRS_PC_G0	64	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDRS_PC_G1	65	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDRS_PC_G2	66	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDC_PC_G0		67	/* PC relative (LDC, STC).  */
+#define R_ARM_LDC_PC_G1		68	/* PC relative (LDC, STC).  */
+#define R_ARM_LDC_PC_G2		69	/* PC relative (LDC, STC).  */
+#define R_ARM_ALU_SB_G0_NC	70	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G0		71	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G1_NC	72	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G1		73	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G2		74	/* Program base relative (ADD,SUB).  */
+#define R_ARM_LDR_SB_G0		75	/* Program base relative (LDR,
+					   STR, LDRB, STRB).  */
+#define R_ARM_LDR_SB_G1		76	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDR_SB_G2		77	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G0	78	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G1	79	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G2	80	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDC_SB_G0		81	/* Program base relative (LDC,STC).  */
+#define R_ARM_LDC_SB_G1		82	/* Program base relative (LDC,STC).  */
+#define R_ARM_LDC_SB_G2		83	/* Program base relative (LDC,STC).  */
+#define R_ARM_MOVW_BREL_NC	84	/* Program base relative 16
+					   bit (MOVW).  */
+#define R_ARM_MOVT_BREL		85	/* Program base relative high
+					   16 bit (MOVT).  */
+#define R_ARM_MOVW_BREL		86	/* Program base relative 16
+					   bit (MOVW).  */
+#define R_ARM_THM_MOVW_BREL_NC	87	/* Program base relative 16
+					   bit (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_BREL	88	/* Program base relative high
+					   16 bit (Thumb32 MOVT).  */
+#define R_ARM_THM_MOVW_BREL	89	/* Program base relative 16
+					   bit (Thumb32 MOVW).  */
+#define R_ARM_TLS_GOTDESC	90
+#define R_ARM_TLS_CALL		91
+#define R_ARM_TLS_DESCSEQ	92	/* TLS relaxation.  */
+#define R_ARM_THM_TLS_CALL	93
+#define R_ARM_PLT32_ABS		94
+#define R_ARM_GOT_ABS		95	/* GOT entry.  */
+#define R_ARM_GOT_PREL		96	/* PC relative GOT entry.  */
+#define R_ARM_GOT_BREL12	97	/* GOT entry relative to GOT
+					   origin (LDR).  */
+#define R_ARM_GOTOFF12		98	/* 12 bit, GOT entry relative
+					   to GOT origin (LDR, STR).  */
+#define R_ARM_GOTRELAX		99
+#define R_ARM_GNU_VTENTRY	100
+#define R_ARM_GNU_VTINHERIT	101
+#define R_ARM_THM_PC11		102	/* PC relative & 0xFFE (Thumb16 B).  */
+#define R_ARM_THM_PC9		103	/* PC relative & 0x1FE
+					   (Thumb16 B/B<cond>).  */
+#define R_ARM_TLS_GD32		104	/* PC-rel 32 bit for global dynamic
+					   thread local data */
+#define R_ARM_TLS_LDM32		105	/* PC-rel 32 bit for local dynamic
+					   thread local data */
+#define R_ARM_TLS_LDO32		106	/* 32 bit offset relative to TLS
+					   block */
+#define R_ARM_TLS_IE32		107	/* PC-rel 32 bit for GOT entry of
+					   static TLS block offset */
+#define R_ARM_TLS_LE32		108	/* 32 bit offset relative to static
+					   TLS block */
+#define R_ARM_TLS_LDO12		109	/* 12 bit relative to TLS
+					   block (LDR, STR).  */
+#define R_ARM_TLS_LE12		110	/* 12 bit relative to static
+					   TLS block (LDR, STR).  */
+#define R_ARM_TLS_IE12GP	111	/* 12 bit GOT entry relative
+					   to GOT origin (LDR).  */
+#define R_ARM_ME_TOO		128	/* Obsolete.  */
+#define R_ARM_THM_TLS_DESCSEQ	129
+#define R_ARM_THM_TLS_DESCSEQ16	129
+#define R_ARM_THM_TLS_DESCSEQ32	130
+#define R_ARM_THM_GOT_BREL12	131	/* GOT entry relative to GOT
+					   origin, 12 bit (Thumb32 LDR).  */
+#define R_ARM_IRELATIVE		160
+#define R_ARM_RXPC25		249
+#define R_ARM_RSBREL32		250
+#define R_ARM_THM_RPC22		251
+#define R_ARM_RREL32		252
+#define R_ARM_RABS22		253
+#define R_ARM_RPC24		254
+#define R_ARM_RBASE		255
+/* Keep this the last entry.  */
+#define R_ARM_NUM		256
+
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS		0x0000000f	/* os-specific flags */
+#define EF_IA_64_ABI64		0x00000010	/* 64-bit ABI */
+#define EF_IA_64_ARCH		0xff000000	/* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT	(PT_LOPROC + 0)	/* arch extension bits */
+#define PT_IA_64_UNWIND		(PT_LOPROC + 1)	/* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT	(PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT	(PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK	(PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV	0x80000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT		(SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND	(SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT		0x10000000	/* section near gp */
+#define SHF_IA_64_NORECOV	0x20000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE	(DT_LOPROC + 0)
+#define DT_IA_64_NUM		1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE		0x00	/* none */
+#define R_IA64_IMM14		0x21	/* symbol + addend, add imm14 */
+#define R_IA64_IMM22		0x22	/* symbol + addend, add imm22 */
+#define R_IA64_IMM64		0x23	/* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB		0x24	/* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB		0x25	/* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB		0x26	/* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB		0x27	/* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22		0x2a	/* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I		0x2b	/* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB	0x2c	/* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB	0x2d	/* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB	0x2e	/* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB	0x2f	/* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22		0x32	/* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I		0x33	/* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22		0x3a	/* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I	0x3b	/* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB	0x3e	/* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB	0x3f	/* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I		0x43	/* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB	0x44	/* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB	0x45	/* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB	0x46	/* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB	0x47	/* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B		0x48	/* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B		0x49	/* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M		0x4a	/* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F		0x4b	/* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB	0x4c	/* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB	0x4d	/* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB	0x4e	/* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB	0x4f	/* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22	0x52	/* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I	0x53	/* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB	0x54	/* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB	0x55	/* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB	0x56	/* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB	0x57	/* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB	0x5c	/* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB	0x5d	/* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB	0x5e	/* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB	0x5f	/* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB	0x64	/* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB	0x65	/* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB	0x66	/* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB	0x67	/* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB		0x6c	/* data 4 + REL */
+#define R_IA64_REL32LSB		0x6d	/* data 4 + REL */
+#define R_IA64_REL64MSB		0x6e	/* data 8 + REL */
+#define R_IA64_REL64LSB		0x6f	/* data 8 + REL */
+#define R_IA64_LTV32MSB		0x74	/* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB		0x75	/* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB		0x76	/* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB		0x77	/* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI	0x79	/* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22		0x7a	/* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I		0x7b	/* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB		0x80	/* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB		0x81	/* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY		0x84	/* copy relocation */
+#define R_IA64_SUB		0x85	/* Addend and symbol difference */
+#define R_IA64_LTOFF22X		0x86	/* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV		0x87	/* Use of LTOFF22X.  */
+#define R_IA64_TPREL14		0x91	/* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22		0x92	/* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I		0x93	/* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB	0x96	/* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB	0x97	/* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22	0x9a	/* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB	0xa6	/* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB	0xa7	/* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22	0xaa	/* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14		0xb1	/* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22		0xb2	/* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I	0xb3	/* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB	0xb4	/* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB	0xb5	/* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB	0xb6	/* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB	0xb7	/* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22	0xba	/* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_SH_MACH_MASK		0x1f
+#define EF_SH_UNKNOWN		0x0
+#define EF_SH1			0x1
+#define EF_SH2			0x2
+#define EF_SH3			0x3
+#define EF_SH_DSP		0x4
+#define EF_SH3_DSP		0x5
+#define EF_SH4AL_DSP		0x6
+#define EF_SH3E			0x8
+#define EF_SH4			0x9
+#define EF_SH2E			0xb
+#define EF_SH4A			0xc
+#define EF_SH2A			0xd
+#define EF_SH4_NOFPU		0x10
+#define EF_SH4A_NOFPU		0x11
+#define EF_SH4_NOMMU_NOFPU	0x12
+#define EF_SH2A_NOFPU		0x13
+#define EF_SH3_NOMMU		0x14
+#define EF_SH2A_SH4_NOFPU	0x15
+#define EF_SH2A_SH3_NOFPU	0x16
+#define EF_SH2A_SH4		0x17
+#define EF_SH2A_SH3E		0x18
+
+/* SH relocs.  */
+#define	R_SH_NONE		0
+#define	R_SH_DIR32		1
+#define	R_SH_REL32		2
+#define	R_SH_DIR8WPN		3
+#define	R_SH_IND12W		4
+#define	R_SH_DIR8WPL		5
+#define	R_SH_DIR8WPZ		6
+#define	R_SH_DIR8BP		7
+#define	R_SH_DIR8W		8
+#define	R_SH_DIR8L		9
+#define	R_SH_SWITCH16		25
+#define	R_SH_SWITCH32		26
+#define	R_SH_USES		27
+#define	R_SH_COUNT		28
+#define	R_SH_ALIGN		29
+#define	R_SH_CODE		30
+#define	R_SH_DATA		31
+#define	R_SH_LABEL		32
+#define	R_SH_SWITCH8		33
+#define	R_SH_GNU_VTINHERIT	34
+#define	R_SH_GNU_VTENTRY	35
+#define	R_SH_TLS_GD_32		144
+#define	R_SH_TLS_LD_32		145
+#define	R_SH_TLS_LDO_32		146
+#define	R_SH_TLS_IE_32		147
+#define	R_SH_TLS_LE_32		148
+#define	R_SH_TLS_DTPMOD32	149
+#define	R_SH_TLS_DTPOFF32	150
+#define	R_SH_TLS_TPOFF32	151
+#define	R_SH_GOT32		160
+#define	R_SH_PLT32		161
+#define	R_SH_COPY		162
+#define	R_SH_GLOB_DAT		163
+#define	R_SH_JMP_SLOT		164
+#define	R_SH_RELATIVE		165
+#define	R_SH_GOTOFF		166
+#define	R_SH_GOTPC		167
+/* Keep this the last entry.  */
+#define	R_SH_NUM		256
+
+/* S/390 specific definitions.  */
+
+/* Valid values for the e_flags field.  */
+
+#define EF_S390_HIGH_GPRS    0x00000001  /* High GPRs kernel facility needed.  */
+
+/* Additional s390 relocs */
+
+#define R_390_NONE		0	/* No reloc.  */
+#define R_390_8			1	/* Direct 8 bit.  */
+#define R_390_12		2	/* Direct 12 bit.  */
+#define R_390_16		3	/* Direct 16 bit.  */
+#define R_390_32		4	/* Direct 32 bit.  */
+#define R_390_PC32		5	/* PC relative 32 bit.	*/
+#define R_390_GOT12		6	/* 12 bit GOT offset.  */
+#define R_390_GOT32		7	/* 32 bit GOT offset.  */
+#define R_390_PLT32		8	/* 32 bit PC relative PLT address.  */
+#define R_390_COPY		9	/* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT		10	/* Create GOT entry.  */
+#define R_390_JMP_SLOT		11	/* Create PLT entry.  */
+#define R_390_RELATIVE		12	/* Adjust by program base.  */
+#define R_390_GOTOFF32		13	/* 32 bit offset to GOT.	 */
+#define R_390_GOTPC		14	/* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16		15	/* 16 bit GOT offset.  */
+#define R_390_PC16		16	/* PC relative 16 bit.	*/
+#define R_390_PC16DBL		17	/* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL		18	/* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL		19	/* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL		20	/* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL		21	/* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64		22	/* Direct 64 bit.  */
+#define R_390_PC64		23	/* PC relative 64 bit.	*/
+#define R_390_GOT64		24	/* 64 bit GOT offset.  */
+#define R_390_PLT64		25	/* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT		26	/* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16		27	/* 16 bit offset to GOT. */
+#define R_390_GOTOFF64		28	/* 64 bit offset to GOT. */
+#define R_390_GOTPLT12		29	/* 12 bit offset to jump slot.	*/
+#define R_390_GOTPLT16		30	/* 16 bit offset to jump slot.	*/
+#define R_390_GOTPLT32		31	/* 32 bit offset to jump slot.	*/
+#define R_390_GOTPLT64		32	/* 64 bit offset to jump slot.	*/
+#define R_390_GOTPLTENT		33	/* 32 bit rel. offset to jump slot.  */
+#define R_390_PLTOFF16		34	/* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32		35	/* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64		36	/* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD		37	/* Tag for load insn in TLS code.  */
+#define R_390_TLS_GDCALL	38	/* Tag for function call in general
+					   dynamic TLS code. */
+#define R_390_TLS_LDCALL	39	/* Tag for function call in local
+					   dynamic TLS code. */
+#define R_390_TLS_GD32		40	/* Direct 32 bit for general dynamic
+					   thread local data.  */
+#define R_390_TLS_GD64		41	/* Direct 64 bit for general dynamic
+					  thread local data.  */
+#define R_390_TLS_GOTIE12	42	/* 12 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_TLS_GOTIE32	43	/* 32 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_TLS_GOTIE64	44	/* 64 bit GOT offset for static TLS
+					   block offset. */
+#define R_390_TLS_LDM32		45	/* Direct 32 bit for local dynamic
+					   thread local data in LE code.  */
+#define R_390_TLS_LDM64		46	/* Direct 64 bit for local dynamic
+					   thread local data in LE code.  */
+#define R_390_TLS_IE32		47	/* 32 bit address of GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_IE64		48	/* 64 bit address of GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_IEENT		49	/* 32 bit rel. offset to GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_LE32		50	/* 32 bit negated offset relative to
+					   static TLS block.  */
+#define R_390_TLS_LE64		51	/* 64 bit negated offset relative to
+					   static TLS block.  */
+#define R_390_TLS_LDO32		52	/* 32 bit offset relative to TLS
+					   block.  */
+#define R_390_TLS_LDO64		53	/* 64 bit offset relative to TLS
+					   block.  */
+#define R_390_TLS_DTPMOD	54	/* ID of module containing symbol.  */
+#define R_390_TLS_DTPOFF	55	/* Offset in TLS block.	 */
+#define R_390_TLS_TPOFF		56	/* Negated offset in static TLS
+					   block.  */
+#define R_390_20		57	/* Direct 20 bit.  */
+#define R_390_GOT20		58	/* 20 bit GOT offset.  */
+#define R_390_GOTPLT20		59	/* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20	60	/* 20 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_IRELATIVE         61      /* STT_GNU_IFUNC relocation.  */
+/* Keep this the last entry.  */
+#define R_390_NUM		62
+
+
+/* CRIS relocations.  */
+#define R_CRIS_NONE		0
+#define R_CRIS_8		1
+#define R_CRIS_16		2
+#define R_CRIS_32		3
+#define R_CRIS_8_PCREL		4
+#define R_CRIS_16_PCREL		5
+#define R_CRIS_32_PCREL		6
+#define R_CRIS_GNU_VTINHERIT	7
+#define R_CRIS_GNU_VTENTRY	8
+#define R_CRIS_COPY		9
+#define R_CRIS_GLOB_DAT		10
+#define R_CRIS_JUMP_SLOT	11
+#define R_CRIS_RELATIVE		12
+#define R_CRIS_16_GOT		13
+#define R_CRIS_32_GOT		14
+#define R_CRIS_16_GOTPLT	15
+#define R_CRIS_32_GOTPLT	16
+#define R_CRIS_32_GOTREL	17
+#define R_CRIS_32_PLT_GOTREL	18
+#define R_CRIS_32_PLT_PCREL	19
+
+#define R_CRIS_NUM		20
+
+
+/* AMD x86-64 relocations.  */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed PC relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64	16	/* ID of module containing symbol */
+#define R_X86_64_DTPOFF64	17	/* Offset in module's TLS block */
+#define R_X86_64_TPOFF64	18	/* Offset in initial TLS block */
+#define R_X86_64_TLSGD		19	/* 32 bit signed PC relative offset
+					   to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD		20	/* 32 bit signed PC relative offset
+					   to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32	21	/* Offset in TLS block */
+#define R_X86_64_GOTTPOFF	22	/* 32 bit signed PC relative offset
+					   to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32	23	/* Offset in initial TLS block */
+#define R_X86_64_PC64		24	/* PC relative 64 bit */
+#define R_X86_64_GOTOFF64	25	/* 64 bit offset to GOT */
+#define R_X86_64_GOTPC32	26	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_GOT64		27	/* 64-bit GOT entry offset */
+#define R_X86_64_GOTPCREL64	28	/* 64-bit PC relative offset
+					   to GOT entry */
+#define R_X86_64_GOTPC64	29	/* 64-bit PC relative offset to GOT */
+#define R_X86_64_GOTPLT64	30 	/* like GOT64, says PLT entry needed */
+#define R_X86_64_PLTOFF64	31	/* 64-bit GOT relative offset
+					   to PLT entry */
+#define R_X86_64_SIZE32		32	/* Size of symbol plus 32-bit addend */
+#define R_X86_64_SIZE64		33	/* Size of symbol plus 64-bit addend */
+#define R_X86_64_GOTPC32_TLSDESC 34	/* GOT offset for TLS descriptor.  */
+#define R_X86_64_TLSDESC_CALL   35	/* Marker for call through TLS
+					   descriptor.  */
+#define R_X86_64_TLSDESC        36	/* TLS descriptor.  */
+#define R_X86_64_IRELATIVE	37	/* Adjust indirectly by program base */
+#define R_X86_64_RELATIVE64	38	/* 64-bit adjust by program base */
+					/* 39 Reserved was R_X86_64_PC32_BND */
+					/* 40 Reserved was R_X86_64_PLT32_BND */
+#define R_X86_64_GOTPCRELX	41	/* Load from 32 bit signed pc relative
+					   offset to GOT entry without REX
+					   prefix, relaxable.  */
+#define R_X86_64_REX_GOTPCRELX	42	/* Load from 32 bit signed pc relative
+					   offset to GOT entry with REX prefix,
+					   relaxable.  */
+#define R_X86_64_NUM		43
+
+
+/* AM33 relocations.  */
+#define R_MN10300_NONE		0	/* No reloc.  */
+#define R_MN10300_32		1	/* Direct 32 bit.  */
+#define R_MN10300_16		2	/* Direct 16 bit.  */
+#define R_MN10300_8		3	/* Direct 8 bit.  */
+#define R_MN10300_PCREL32	4	/* PC-relative 32-bit.  */
+#define R_MN10300_PCREL16	5	/* PC-relative 16-bit signed.  */
+#define R_MN10300_PCREL8	6	/* PC-relative 8-bit signed.  */
+#define R_MN10300_GNU_VTINHERIT	7	/* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY	8	/* ... collection annotation.  */
+#define R_MN10300_24		9	/* Direct 24 bit.  */
+#define R_MN10300_GOTPC32	10	/* 32-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTPC16	11	/* 16-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTOFF32	12	/* 32-bit offset from GOT.  */
+#define R_MN10300_GOTOFF24	13	/* 24-bit offset from GOT.  */
+#define R_MN10300_GOTOFF16	14	/* 16-bit offset from GOT.  */
+#define R_MN10300_PLT32		15	/* 32-bit PCrel to PLT entry.  */
+#define R_MN10300_PLT16		16	/* 16-bit PCrel to PLT entry.  */
+#define R_MN10300_GOT32		17	/* 32-bit offset to GOT entry.  */
+#define R_MN10300_GOT24		18	/* 24-bit offset to GOT entry.  */
+#define R_MN10300_GOT16		19	/* 16-bit offset to GOT entry.  */
+#define R_MN10300_COPY		20	/* Copy symbol at runtime.  */
+#define R_MN10300_GLOB_DAT	21	/* Create GOT entry.  */
+#define R_MN10300_JMP_SLOT	22	/* Create PLT entry.  */
+#define R_MN10300_RELATIVE	23	/* Adjust by program base.  */
+#define R_MN10300_TLS_GD	24	/* 32-bit offset for global dynamic.  */
+#define R_MN10300_TLS_LD	25	/* 32-bit offset for local dynamic.  */
+#define R_MN10300_TLS_LDO	26	/* Module-relative offset.  */
+#define R_MN10300_TLS_GOTIE	27	/* GOT offset for static TLS block
+					   offset.  */
+#define R_MN10300_TLS_IE	28	/* GOT address for static TLS block
+					   offset.  */
+#define R_MN10300_TLS_LE	29	/* Offset relative to static TLS
+					   block.  */
+#define R_MN10300_TLS_DTPMOD	30	/* ID of module containing symbol.  */
+#define R_MN10300_TLS_DTPOFF	31	/* Offset in module TLS block.  */
+#define R_MN10300_TLS_TPOFF	32	/* Offset in static TLS block.  */
+#define R_MN10300_SYM_DIFF	33	/* Adjustment for next reloc as needed
+					   by linker relaxation.  */
+#define R_MN10300_ALIGN		34	/* Alignment requirement for linker
+					   relaxation.  */
+#define R_MN10300_NUM		35
+
+
+/* M32R relocs.  */
+#define R_M32R_NONE		0	/* No reloc. */
+#define R_M32R_16		1	/* Direct 16 bit. */
+#define R_M32R_32		2	/* Direct 32 bit. */
+#define R_M32R_24		3	/* Direct 24 bit. */
+#define R_M32R_10_PCREL		4	/* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL		5	/* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL		6	/* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO		7	/* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO		8	/* High 16 bit with signed low. */
+#define R_M32R_LO16		9	/* Low 16 bit. */
+#define R_M32R_SDA16		10	/* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT	11
+#define R_M32R_GNU_VTENTRY	12
+/* M32R relocs use SHT_RELA.  */
+#define R_M32R_16_RELA		33	/* Direct 16 bit. */
+#define R_M32R_32_RELA		34	/* Direct 32 bit. */
+#define R_M32R_24_RELA		35	/* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA	36	/* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA	37	/* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA	38	/* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA	39	/* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA	40	/* High 16 bit with signed low */
+#define R_M32R_LO16_RELA	41	/* Low 16 bit */
+#define R_M32R_SDA16_RELA	42	/* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT	43
+#define R_M32R_RELA_GNU_VTENTRY	44
+#define R_M32R_REL32		45	/* PC relative 32 bit.  */
+
+#define R_M32R_GOT24		48	/* 24 bit GOT entry */
+#define R_M32R_26_PLTREL	49	/* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY		50	/* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT		51	/* Create GOT entry */
+#define R_M32R_JMP_SLOT		52	/* Create PLT entry */
+#define R_M32R_RELATIVE		53	/* Adjust by program base */
+#define R_M32R_GOTOFF		54	/* 24 bit offset to GOT */
+#define R_M32R_GOTPC24		55	/* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO	56	/* High 16 bit GOT entry with unsigned
+					   low */
+#define R_M32R_GOT16_HI_SLO	57	/* High 16 bit GOT entry with signed
+					   low */
+#define R_M32R_GOT16_LO		58	/* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO	59	/* High 16 bit PC relative offset to
+					   GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO	60	/* High 16 bit PC relative offset to
+					   GOT with signed low */
+#define R_M32R_GOTPC_LO		61	/* Low 16 bit PC relative offset to
+					   GOT */
+#define R_M32R_GOTOFF_HI_ULO	62	/* High 16 bit offset to GOT
+					   with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO	63	/* High 16 bit offset to GOT
+					   with signed low */
+#define R_M32R_GOTOFF_LO	64	/* Low 16 bit offset to GOT */
+#define R_M32R_NUM		256	/* Keep this the last entry. */
+
+/* MicroBlaze relocations */
+#define R_MICROBLAZE_NONE		0	/* No reloc. */
+#define R_MICROBLAZE_32 		1	/* Direct 32 bit. */
+#define R_MICROBLAZE_32_PCREL		2	/* PC relative 32 bit. */
+#define R_MICROBLAZE_64_PCREL		3	/* PC relative 64 bit. */
+#define R_MICROBLAZE_32_PCREL_LO	4	/* Low 16 bits of PCREL32. */
+#define R_MICROBLAZE_64 		5	/* Direct 64 bit. */
+#define R_MICROBLAZE_32_LO		6	/* Low 16 bit. */
+#define R_MICROBLAZE_SRO32		7	/* Read-only small data area. */
+#define R_MICROBLAZE_SRW32		8	/* Read-write small data area. */
+#define R_MICROBLAZE_64_NONE		9	/* No reloc. */
+#define R_MICROBLAZE_32_SYM_OP_SYM	10	/* Symbol Op Symbol relocation. */
+#define R_MICROBLAZE_GNU_VTINHERIT	11	/* GNU C++ vtable hierarchy. */
+#define R_MICROBLAZE_GNU_VTENTRY	12	/* GNU C++ vtable member usage. */
+#define R_MICROBLAZE_GOTPC_64		13	/* PC-relative GOT offset.  */
+#define R_MICROBLAZE_GOT_64		14	/* GOT entry offset.  */
+#define R_MICROBLAZE_PLT_64		15	/* PLT offset (PC-relative).  */
+#define R_MICROBLAZE_REL		16	/* Adjust by program base.  */
+#define R_MICROBLAZE_JUMP_SLOT		17	/* Create PLT entry.  */
+#define R_MICROBLAZE_GLOB_DAT		18	/* Create GOT entry.  */
+#define R_MICROBLAZE_GOTOFF_64		19	/* 64 bit offset to GOT. */
+#define R_MICROBLAZE_GOTOFF_32		20	/* 32 bit offset to GOT. */
+#define R_MICROBLAZE_COPY		21	/* Runtime copy.  */
+#define R_MICROBLAZE_TLS		22	/* TLS Reloc. */
+#define R_MICROBLAZE_TLSGD		23	/* TLS General Dynamic. */
+#define R_MICROBLAZE_TLSLD		24	/* TLS Local Dynamic. */
+#define R_MICROBLAZE_TLSDTPMOD32	25	/* TLS Module ID. */
+#define R_MICROBLAZE_TLSDTPREL32	26	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSDTPREL64	27	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSGOTTPREL32	28	/* TLS Offset From Thread Pointer. */
+#define R_MICROBLAZE_TLSTPREL32 	29	/* TLS Offset From Thread Pointer. */
+
+/* Legal values for d_tag (dynamic entry type).  */
+#define DT_NIOS2_GP             0x70000002 /* Address of _gp.  */
+
+/* Nios II relocations.  */
+#define R_NIOS2_NONE		0	/* No reloc.  */
+#define R_NIOS2_S16		1	/* Direct signed 16 bit.  */
+#define R_NIOS2_U16		2	/* Direct unsigned 16 bit.  */
+#define R_NIOS2_PCREL16		3	/* PC relative 16 bit.  */
+#define R_NIOS2_CALL26		4	/* Direct call.  */
+#define R_NIOS2_IMM5		5	/* 5 bit constant expression.  */
+#define R_NIOS2_CACHE_OPX	6	/* 5 bit expression, shift 22.  */
+#define R_NIOS2_IMM6		7	/* 6 bit constant expression.  */
+#define R_NIOS2_IMM8		8	/* 8 bit constant expression.  */
+#define R_NIOS2_HI16		9	/* High 16 bit.  */
+#define R_NIOS2_LO16		10	/* Low 16 bit.  */
+#define R_NIOS2_HIADJ16		11	/* High 16 bit, adjusted.  */
+#define R_NIOS2_BFD_RELOC_32	12	/* 32 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_16	13	/* 16 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_8	14	/* 8 bit symbol value + addend.  */
+#define R_NIOS2_GPREL		15	/* 16 bit GP pointer offset.  */
+#define R_NIOS2_GNU_VTINHERIT	16	/* GNU C++ vtable hierarchy.  */
+#define R_NIOS2_GNU_VTENTRY	17	/* GNU C++ vtable member usage.  */
+#define R_NIOS2_UJMP		18	/* Unconditional branch.  */
+#define R_NIOS2_CJMP		19	/* Conditional branch.  */
+#define R_NIOS2_CALLR		20	/* Indirect call through register.  */
+#define R_NIOS2_ALIGN		21	/* Alignment requirement for
+					   linker relaxation.  */
+#define R_NIOS2_GOT16		22	/* 16 bit GOT entry.  */
+#define R_NIOS2_CALL16		23	/* 16 bit GOT entry for function.  */
+#define R_NIOS2_GOTOFF_LO	24	/* %lo of offset to GOT pointer.  */
+#define R_NIOS2_GOTOFF_HA	25	/* %hiadj of offset to GOT pointer.  */
+#define R_NIOS2_PCREL_LO	26	/* %lo of PC relative offset.  */
+#define R_NIOS2_PCREL_HA	27	/* %hiadj of PC relative offset.  */
+#define R_NIOS2_TLS_GD16	28	/* 16 bit GOT offset for TLS GD.  */
+#define R_NIOS2_TLS_LDM16	29	/* 16 bit GOT offset for TLS LDM.  */
+#define R_NIOS2_TLS_LDO16	30	/* 16 bit module relative offset.  */
+#define R_NIOS2_TLS_IE16	31	/* 16 bit GOT offset for TLS IE.  */
+#define R_NIOS2_TLS_LE16	32	/* 16 bit LE TP-relative offset.  */
+#define R_NIOS2_TLS_DTPMOD	33	/* Module number.  */
+#define R_NIOS2_TLS_DTPREL	34	/* Module-relative offset.  */
+#define R_NIOS2_TLS_TPREL	35	/* TP-relative offset.  */
+#define R_NIOS2_COPY		36	/* Copy symbol at runtime.  */
+#define R_NIOS2_GLOB_DAT	37	/* Create GOT entry.  */
+#define R_NIOS2_JUMP_SLOT	38	/* Create PLT entry.  */
+#define R_NIOS2_RELATIVE	39	/* Adjust by program base.  */
+#define R_NIOS2_GOTOFF		40	/* 16 bit offset to GOT pointer.  */
+#define R_NIOS2_CALL26_NOAT	41	/* Direct call in .noat section.  */
+#define R_NIOS2_GOT_LO		42	/* %lo() of GOT entry.  */
+#define R_NIOS2_GOT_HA		43	/* %hiadj() of GOT entry.  */
+#define R_NIOS2_CALL_LO		44	/* %lo() of function GOT entry.  */
+#define R_NIOS2_CALL_HA		45	/* %hiadj() of function GOT entry.  */
+
+/* TILEPro relocations.  */
+#define R_TILEPRO_NONE		0	/* No reloc */
+#define R_TILEPRO_32		1	/* Direct 32 bit */
+#define R_TILEPRO_16		2	/* Direct 16 bit */
+#define R_TILEPRO_8		3	/* Direct 8 bit */
+#define R_TILEPRO_32_PCREL	4	/* PC relative 32 bit */
+#define R_TILEPRO_16_PCREL	5	/* PC relative 16 bit */
+#define R_TILEPRO_8_PCREL	6	/* PC relative 8 bit */
+#define R_TILEPRO_LO16		7	/* Low 16 bit */
+#define R_TILEPRO_HI16		8	/* High 16 bit */
+#define R_TILEPRO_HA16		9	/* High 16 bit, adjusted */
+#define R_TILEPRO_COPY		10	/* Copy relocation */
+#define R_TILEPRO_GLOB_DAT	11	/* Create GOT entry */
+#define R_TILEPRO_JMP_SLOT	12	/* Create PLT entry */
+#define R_TILEPRO_RELATIVE	13	/* Adjust by program base */
+#define R_TILEPRO_BROFF_X1	14	/* X1 pipe branch offset */
+#define R_TILEPRO_JOFFLONG_X1	15	/* X1 pipe jump offset */
+#define R_TILEPRO_JOFFLONG_X1_PLT 16	/* X1 pipe jump offset to PLT */
+#define R_TILEPRO_IMM8_X0	17	/* X0 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y0	18	/* Y0 pipe 8-bit */
+#define R_TILEPRO_IMM8_X1	19	/* X1 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y1	20	/* Y1 pipe 8-bit */
+#define R_TILEPRO_MT_IMM15_X1	21	/* X1 pipe mtspr */
+#define R_TILEPRO_MF_IMM15_X1	22	/* X1 pipe mfspr */
+#define R_TILEPRO_IMM16_X0	23	/* X0 pipe 16-bit */
+#define R_TILEPRO_IMM16_X1	24	/* X1 pipe 16-bit */
+#define R_TILEPRO_IMM16_X0_LO	25	/* X0 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X1_LO	26	/* X1 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X0_HI	27	/* X0 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X1_HI	28	/* X1 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X0_HA	29	/* X0 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X1_HA	30	/* X1 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X0_PCREL 31	/* X0 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X1_PCREL 32	/* X1 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X0_LO_PCREL 33	/* X0 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X1_LO_PCREL 34	/* X1 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X0_HI_PCREL 35	/* X0 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X1_HI_PCREL 36	/* X1 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X0_HA_PCREL 37	/* X0 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X1_HA_PCREL 38	/* X1 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X0_GOT	39	/* X0 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT	40	/* X1 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_LO 41	/* X0 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_LO 42	/* X1 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HI 43	/* X0 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HI 44	/* X1 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HA 45	/* X0 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HA 46	/* X1 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_MMSTART_X0	47	/* X0 pipe mm "start" */
+#define R_TILEPRO_MMEND_X0	48	/* X0 pipe mm "end" */
+#define R_TILEPRO_MMSTART_X1	49	/* X1 pipe mm "start" */
+#define R_TILEPRO_MMEND_X1	50	/* X1 pipe mm "end" */
+#define R_TILEPRO_SHAMT_X0	51	/* X0 pipe shift amount */
+#define R_TILEPRO_SHAMT_X1	52	/* X1 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y0	53	/* Y0 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y1	54	/* Y1 pipe shift amount */
+#define R_TILEPRO_DEST_IMM8_X1	55	/* X1 pipe destination 8-bit */
+/* Relocs 56-59 are currently not defined.  */
+#define R_TILEPRO_TLS_GD_CALL	60	/* "jal" for TLS GD */
+#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61	/* X0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62	/* X1 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63	/* Y0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64	/* Y1 pipe "addi" for TLS GD */
+#define R_TILEPRO_TLS_IE_LOAD	65	/* "lw_tls" for TLS IE */
+#define R_TILEPRO_IMM16_X0_TLS_GD 66	/* X0 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD 67	/* X1 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68	/* X0 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69	/* X1 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70	/* X0 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71	/* X1 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72	/* X0 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73	/* X1 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE 74	/* X0 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE 75	/* X1 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76	/* X0 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77	/* X1 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78	/* X0 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79	/* X1 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80	/* X0 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81	/* X1 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_TLS_DTPMOD32	82	/* ID of module containing symbol */
+#define R_TILEPRO_TLS_DTPOFF32	83	/* Offset in TLS block */
+#define R_TILEPRO_TLS_TPOFF32	84	/* Offset in static TLS block */
+#define R_TILEPRO_IMM16_X0_TLS_LE 85	/* X0 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE 86	/* X1 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87	/* X0 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88	/* X1 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89	/* X0 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90	/* X1 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91	/* X0 pipe ha() 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92	/* X1 pipe ha() 16-bit TLS LE offset */
+
+#define R_TILEPRO_GNU_VTINHERIT	128	/* GNU C++ vtable hierarchy */
+#define R_TILEPRO_GNU_VTENTRY	129	/* GNU C++ vtable member usage */
+
+#define R_TILEPRO_NUM		130
+
+
+/* TILE-Gx relocations.  */
+#define R_TILEGX_NONE		0	/* No reloc */
+#define R_TILEGX_64		1	/* Direct 64 bit */
+#define R_TILEGX_32		2	/* Direct 32 bit */
+#define R_TILEGX_16		3	/* Direct 16 bit */
+#define R_TILEGX_8		4	/* Direct 8 bit */
+#define R_TILEGX_64_PCREL	5	/* PC relative 64 bit */
+#define R_TILEGX_32_PCREL	6	/* PC relative 32 bit */
+#define R_TILEGX_16_PCREL	7	/* PC relative 16 bit */
+#define R_TILEGX_8_PCREL	8	/* PC relative 8 bit */
+#define R_TILEGX_HW0		9	/* hword 0 16-bit */
+#define R_TILEGX_HW1		10	/* hword 1 16-bit */
+#define R_TILEGX_HW2		11	/* hword 2 16-bit */
+#define R_TILEGX_HW3		12	/* hword 3 16-bit */
+#define R_TILEGX_HW0_LAST	13	/* last hword 0 16-bit */
+#define R_TILEGX_HW1_LAST	14	/* last hword 1 16-bit */
+#define R_TILEGX_HW2_LAST	15	/* last hword 2 16-bit */
+#define R_TILEGX_COPY		16	/* Copy relocation */
+#define R_TILEGX_GLOB_DAT	17	/* Create GOT entry */
+#define R_TILEGX_JMP_SLOT	18	/* Create PLT entry */
+#define R_TILEGX_RELATIVE	19	/* Adjust by program base */
+#define R_TILEGX_BROFF_X1	20	/* X1 pipe branch offset */
+#define R_TILEGX_JUMPOFF_X1	21	/* X1 pipe jump offset */
+#define R_TILEGX_JUMPOFF_X1_PLT	22	/* X1 pipe jump offset to PLT */
+#define R_TILEGX_IMM8_X0	23	/* X0 pipe 8-bit */
+#define R_TILEGX_IMM8_Y0	24	/* Y0 pipe 8-bit */
+#define R_TILEGX_IMM8_X1	25	/* X1 pipe 8-bit */
+#define R_TILEGX_IMM8_Y1	26	/* Y1 pipe 8-bit */
+#define R_TILEGX_DEST_IMM8_X1	27	/* X1 pipe destination 8-bit */
+#define R_TILEGX_MT_IMM14_X1	28	/* X1 pipe mtspr */
+#define R_TILEGX_MF_IMM14_X1	29	/* X1 pipe mfspr */
+#define R_TILEGX_MMSTART_X0	30	/* X0 pipe mm "start" */
+#define R_TILEGX_MMEND_X0	31	/* X0 pipe mm "end" */
+#define R_TILEGX_SHAMT_X0	32	/* X0 pipe shift amount */
+#define R_TILEGX_SHAMT_X1	33	/* X1 pipe shift amount */
+#define R_TILEGX_SHAMT_Y0	34	/* Y0 pipe shift amount */
+#define R_TILEGX_SHAMT_Y1	35	/* Y1 pipe shift amount */
+#define R_TILEGX_IMM16_X0_HW0	36	/* X0 pipe hword 0 */
+#define R_TILEGX_IMM16_X1_HW0	37	/* X1 pipe hword 0 */
+#define R_TILEGX_IMM16_X0_HW1	38	/* X0 pipe hword 1 */
+#define R_TILEGX_IMM16_X1_HW1	39	/* X1 pipe hword 1 */
+#define R_TILEGX_IMM16_X0_HW2	40	/* X0 pipe hword 2 */
+#define R_TILEGX_IMM16_X1_HW2	41	/* X1 pipe hword 2 */
+#define R_TILEGX_IMM16_X0_HW3	42	/* X0 pipe hword 3 */
+#define R_TILEGX_IMM16_X1_HW3	43	/* X1 pipe hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST 44	/* X0 pipe last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST 45	/* X1 pipe last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST 46	/* X0 pipe last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST 47	/* X1 pipe last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST 48	/* X0 pipe last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST 49	/* X1 pipe last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_PCREL 50	/* X0 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PCREL 51	/* X1 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PCREL 52	/* X0 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PCREL 53	/* X1 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PCREL 54	/* X0 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PCREL 55	/* X1 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X0_HW3_PCREL 56	/* X0 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PCREL 57	/* X1 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_GOT 64	/* X0 pipe hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_GOT 65	/* X1 pipe hword 0 GOT offset */
+#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */
+#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */
+#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78	/* X0 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79	/* X1 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80	/* X0 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81	/* X1 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */
+/* Relocs 90-91 are currently not defined.  */
+#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92	/* X0 pipe hword 0 TLS IE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93	/* X1 pipe hword 0 TLS IE offset */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */
+/* Relocs 104-105 are currently not defined.  */
+#define R_TILEGX_TLS_DTPMOD64	106	/* 64-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF64	107	/* 64-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF64	108	/* 64-bit offset in static TLS block */
+#define R_TILEGX_TLS_DTPMOD32	109	/* 32-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF32	110	/* 32-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF32	111	/* 32-bit offset in static TLS block */
+#define R_TILEGX_TLS_GD_CALL	112	/* "jal" for TLS GD */
+#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113	/* X0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114	/* X1 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115	/* Y0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116	/* Y1 pipe "addi" for TLS GD */
+#define R_TILEGX_TLS_IE_LOAD	117	/* "ld_tls" for TLS IE */
+#define R_TILEGX_IMM8_X0_TLS_ADD 118	/* X0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_X1_TLS_ADD 119	/* X1 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y0_TLS_ADD 120	/* Y0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y1_TLS_ADD 121	/* Y1 pipe "addi" for TLS GD/IE */
+
+#define R_TILEGX_GNU_VTINHERIT	128	/* GNU C++ vtable hierarchy */
+#define R_TILEGX_GNU_VTENTRY	129	/* GNU C++ vtable member usage */
+
+#define R_TILEGX_NUM		130
+
+/* BPF specific declarations.  */
+
+#define R_BPF_NONE		0	/* No reloc */
+#define R_BPF_MAP_FD		1	/* Map fd to pointer */
+
+/* Imagination Meta specific relocations. */
+
+#define R_METAG_HIADDR16	0
+#define R_METAG_LOADDR16	1
+#define R_METAG_ADDR32		2	/* 32bit absolute address */
+#define R_METAG_NONE		3	/* No reloc */
+#define R_METAG_RELBRANCH	4
+#define R_METAG_GETSETOFF	5
+
+/* Backward compatability */
+#define R_METAG_REG32OP1	6
+#define R_METAG_REG32OP2	7
+#define R_METAG_REG32OP3	8
+#define R_METAG_REG16OP1	9
+#define R_METAG_REG16OP2	10
+#define R_METAG_REG16OP3	11
+#define R_METAG_REG32OP4	12
+
+#define R_METAG_HIOG		13
+#define R_METAG_LOOG		14
+
+#define R_METAG_REL8		15
+#define R_METAG_REL16		16
+
+/* GNU */
+#define R_METAG_GNU_VTINHERIT	30
+#define R_METAG_GNU_VTENTRY	31
+
+/* PIC relocations */
+#define R_METAG_HI16_GOTOFF	32
+#define R_METAG_LO16_GOTOFF	33
+#define R_METAG_GETSET_GOTOFF	34
+#define R_METAG_GETSET_GOT	35
+#define R_METAG_HI16_GOTPC	36
+#define R_METAG_LO16_GOTPC	37
+#define R_METAG_HI16_PLT	38
+#define R_METAG_LO16_PLT	39
+#define R_METAG_RELBRANCH_PLT	40
+#define R_METAG_GOTOFF		41
+#define R_METAG_PLT		42
+#define R_METAG_COPY		43
+#define R_METAG_JMP_SLOT	44
+#define R_METAG_RELATIVE	45
+#define R_METAG_GLOB_DAT	46
+
+/* TLS relocations */
+#define R_METAG_TLS_GD		47
+#define R_METAG_TLS_LDM		48
+#define R_METAG_TLS_LDO_HI16	49
+#define R_METAG_TLS_LDO_LO16	50
+#define R_METAG_TLS_LDO		51
+#define R_METAG_TLS_IE		52
+#define R_METAG_TLS_IENONPIC	53
+#define R_METAG_TLS_IENONPIC_HI16 54
+#define R_METAG_TLS_IENONPIC_LO16 55
+#define R_METAG_TLS_TPOFF	56
+#define R_METAG_TLS_DTPMOD	57
+#define R_METAG_TLS_DTPOFF	58
+#define R_METAG_TLS_LE		59
+#define R_METAG_TLS_LE_HI16	60
+#define R_METAG_TLS_LE_LO16	61
+
+__END_DECLS
+
+#endif	/* elf.h */
diff --git a/REORG.TODO/elf/enbl-secure.c b/REORG.TODO/elf/enbl-secure.c
new file mode 100644
index 0000000000..c0723774d9
--- /dev/null
+++ b/REORG.TODO/elf/enbl-secure.c
@@ -0,0 +1,36 @@
+/* Define and initialize the `__libc_enable_secure' flag.  Generic version.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is used in the static libc.  For the shared library,
+   dl-sysdep.c defines and initializes __libc_enable_secure.  */
+
+#include <unistd.h>
+#include <libc-internal.h>
+
+/* If nonzero __libc_enable_secure is already set.  */
+int __libc_enable_secure_decided;
+/* Safest assumption, if somehow the initializer isn't run.  */
+int __libc_enable_secure = 1;
+
+void
+__libc_init_secure (void)
+{
+  if (__libc_enable_secure_decided == 0)
+    __libc_enable_secure = (__geteuid () != __getuid ()
+			    || __getegid () != __getgid ());
+}
diff --git a/REORG.TODO/elf/failobj.c b/REORG.TODO/elf/failobj.c
new file mode 100644
index 0000000000..500606382e
--- /dev/null
+++ b/REORG.TODO/elf/failobj.c
@@ -0,0 +1,10 @@
+/* This function is supposed to not exist.  */
+extern int xyzzy (int);
+
+extern int foo (int);
+
+int
+foo (int a)
+{
+  return xyzzy (a);
+}
diff --git a/REORG.TODO/elf/filter.c b/REORG.TODO/elf/filter.c
new file mode 100644
index 0000000000..46aa15ba16
--- /dev/null
+++ b/REORG.TODO/elf/filter.c
@@ -0,0 +1,19 @@
+#include <mcheck.h>
+#include <stdio.h>
+#include <string.h>
+
+extern const char *foo (void);
+
+int
+main (void)
+{
+  const char *s;
+
+  mtrace ();
+
+  s = foo ();
+
+  printf ("called `foo' from `%s'\n", s);
+
+  return strcmp (s, "filtmod2.c");
+}
diff --git a/REORG.TODO/elf/filtmod1.c b/REORG.TODO/elf/filtmod1.c
new file mode 100644
index 0000000000..1d9b19481d
--- /dev/null
+++ b/REORG.TODO/elf/filtmod1.c
@@ -0,0 +1,7 @@
+extern const char *foo (void);
+
+const char *
+foo (void)
+{
+  return __FILE__;
+}
diff --git a/REORG.TODO/elf/filtmod2.c b/REORG.TODO/elf/filtmod2.c
new file mode 100644
index 0000000000..1d9b19481d
--- /dev/null
+++ b/REORG.TODO/elf/filtmod2.c
@@ -0,0 +1,7 @@
+extern const char *foo (void);
+
+const char *
+foo (void)
+{
+  return __FILE__;
+}
diff --git a/REORG.TODO/elf/firstobj.c b/REORG.TODO/elf/firstobj.c
new file mode 100644
index 0000000000..2e6033eab6
--- /dev/null
+++ b/REORG.TODO/elf/firstobj.c
@@ -0,0 +1,10 @@
+#include <errno.h>
+
+extern int foo (void);
+
+int
+foo (void)
+{
+  errno = 0;
+  return 0;
+}
diff --git a/REORG.TODO/elf/gen-trusted-dirs.awk b/REORG.TODO/elf/gen-trusted-dirs.awk
new file mode 100644
index 0000000000..59f10a4856
--- /dev/null
+++ b/REORG.TODO/elf/gen-trusted-dirs.awk
@@ -0,0 +1,37 @@
+BEGIN {
+  FS = " ";
+}
+
+{
+  for (i = 1; i <= NF; ++i) {
+    s[cnt++] = $i"/";
+  }
+}
+
+END {
+  printf ("#define SYSTEM_DIRS \\\n");
+
+  printf ("  \"%s\"", s[0]);
+
+  for (i = 1; i < cnt; ++i) {
+    printf (" \"\\0\" \"%s\"", s[i]);
+  }
+
+  printf ("\n\n");
+
+  printf ("#define SYSTEM_DIRS_LEN \\\n");
+
+  printf ("  %d", length (s[0]));
+  m = length (s[0]);
+
+  for (i = 1; i < cnt; ++i) {
+    printf (", %d", length(s[i]));
+    if (length(s[i]) > m) {
+      m = length(s[i]);
+    }
+  }
+
+  printf ("\n\n");
+
+  printf ("#define SYSTEM_DIRS_MAX_LEN\t%d\n", m);
+}
diff --git a/REORG.TODO/elf/genrtldtbl.awk b/REORG.TODO/elf/genrtldtbl.awk
new file mode 100644
index 0000000000..0e2a374901
--- /dev/null
+++ b/REORG.TODO/elf/genrtldtbl.awk
@@ -0,0 +1,29 @@
+#!/usr/bin/awk
+BEGIN {
+  FS=":";
+  count=0;
+}
+{
+  for (i = 1; i <= NF; ++i) {
+    gsub (/\/*$/, "", $i);
+    dir[count++] = $i;
+  }
+}
+END {
+  for (i = 0; i < count; ++i) {
+    printf ("static struct r_search_path_elem rtld_search_dir%d =\n", i+1);
+    printf ("  { \"%s/\", %d, unknown, 0, nonexisting, NULL, NULL, ",
+	    dir[i], length (dir[i]) + 1);
+    if (i== 0)
+      printf ("NULL };\n");
+    else
+      printf ("&rtld_search_dir%d };\n", i);
+  }
+  printf ("\nstatic struct r_search_path_elem *rtld_search_dirs[] =\n{\n");
+  for (i = 0; i < count; ++i) {
+    printf ("  &rtld_search_dir%d,\n", i + 1);
+  }
+  printf ("  NULL\n};\n\n");
+  printf ("static struct r_search_path_elem *all_dirs = &rtld_search_dir%d;\n",
+	  count);
+}
diff --git a/REORG.TODO/elf/get-dynamic-info.h b/REORG.TODO/elf/get-dynamic-info.h
new file mode 100644
index 0000000000..7525c3a5b2
--- /dev/null
+++ b/REORG.TODO/elf/get-dynamic-info.h
@@ -0,0 +1,184 @@
+/* Read the dynamic section at DYN and fill in INFO with indices DT_*.
+   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is included multiple times and therefore lacks a header
+   file inclusion guard.  */
+
+#include <assert.h>
+#include <libc-diag.h>
+
+#ifndef RESOLVE_MAP
+static
+#else
+auto
+#endif
+inline void __attribute__ ((unused, always_inline))
+elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
+{
+  ElfW(Dyn) *dyn = l->l_ld;
+  ElfW(Dyn) **info;
+#if __ELF_NATIVE_CLASS == 32
+  typedef Elf32_Word d_tag_utype;
+#elif __ELF_NATIVE_CLASS == 64
+  typedef Elf64_Xword d_tag_utype;
+#endif
+
+#ifndef RTLD_BOOTSTRAP
+  if (dyn == NULL)
+    return;
+#endif
+
+  info = l->l_info;
+
+  while (dyn->d_tag != DT_NULL)
+    {
+      if ((d_tag_utype) dyn->d_tag < DT_NUM)
+	info[dyn->d_tag] = dyn;
+      else if (dyn->d_tag >= DT_LOPROC &&
+	       dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
+	{
+	  /* This does not violate the array bounds of l->l_info, but
+	     gcc 4.6 on sparc somehow does not see this.  */
+	  DIAG_PUSH_NEEDS_COMMENT;
+	  DIAG_IGNORE_NEEDS_COMMENT (4.6,
+				     "-Warray-bounds");
+	  info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
+	  DIAG_POP_NEEDS_COMMENT;
+	}
+      else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
+	info[VERSYMIDX (dyn->d_tag)] = dyn;
+      else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
+	info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+	     + DT_VERSIONTAGNUM] = dyn;
+      else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
+	info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+	     + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
+      else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
+	info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+	     + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
+      ++dyn;
+    }
+
+#define DL_RO_DYN_TEMP_CNT	8
+
+#ifndef DL_RO_DYN_SECTION
+  /* Don't adjust .dynamic unnecessarily.  */
+  if (l->l_addr != 0)
+    {
+      ElfW(Addr) l_addr = l->l_addr;
+      int cnt = 0;
+
+# define ADJUST_DYN_INFO(tag) \
+      do								      \
+	if (info[tag] != NULL)						      \
+	  {								      \
+	    if (temp)							      \
+	      {								      \
+		temp[cnt].d_tag = info[tag]->d_tag;			      \
+		temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr;	      \
+		info[tag] = temp + cnt++;				      \
+	      }								      \
+	    else							      \
+	      info[tag]->d_un.d_ptr += l_addr;				      \
+	  }								      \
+      while (0)
+
+      ADJUST_DYN_INFO (DT_HASH);
+      ADJUST_DYN_INFO (DT_PLTGOT);
+      ADJUST_DYN_INFO (DT_STRTAB);
+      ADJUST_DYN_INFO (DT_SYMTAB);
+# if ! ELF_MACHINE_NO_RELA
+      ADJUST_DYN_INFO (DT_RELA);
+# endif
+# if ! ELF_MACHINE_NO_REL
+      ADJUST_DYN_INFO (DT_REL);
+# endif
+      ADJUST_DYN_INFO (DT_JMPREL);
+      ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
+      ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
+		       + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
+# undef ADJUST_DYN_INFO
+      assert (cnt <= DL_RO_DYN_TEMP_CNT);
+    }
+#endif
+  if (info[DT_PLTREL] != NULL)
+    {
+#if ELF_MACHINE_NO_RELA
+      assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
+#elif ELF_MACHINE_NO_REL
+      assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
+#else
+      assert (info[DT_PLTREL]->d_un.d_val == DT_REL
+	      || info[DT_PLTREL]->d_un.d_val == DT_RELA);
+#endif
+    }
+#if ! ELF_MACHINE_NO_RELA
+  if (info[DT_RELA] != NULL)
+    assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
+# endif
+# if ! ELF_MACHINE_NO_REL
+  if (info[DT_REL] != NULL)
+    assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
+#endif
+#ifdef RTLD_BOOTSTRAP
+  /* Only the bind now flags are allowed.  */
+  assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
+	  || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
+  assert (info[DT_FLAGS] == NULL
+	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
+  /* Flags must not be set for ld.so.  */
+  assert (info[DT_RUNPATH] == NULL);
+  assert (info[DT_RPATH] == NULL);
+#else
+  if (info[DT_FLAGS] != NULL)
+    {
+      /* Flags are used.  Translate to the old form where available.
+	 Since these l_info entries are only tested for NULL pointers it
+	 is ok if they point to the DT_FLAGS entry.  */
+      l->l_flags = info[DT_FLAGS]->d_un.d_val;
+
+      if (l->l_flags & DF_SYMBOLIC)
+	info[DT_SYMBOLIC] = info[DT_FLAGS];
+      if (l->l_flags & DF_TEXTREL)
+	info[DT_TEXTREL] = info[DT_FLAGS];
+      if (l->l_flags & DF_BIND_NOW)
+	info[DT_BIND_NOW] = info[DT_FLAGS];
+    }
+  if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
+    {
+      l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
+
+      /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
+	 to assert this, but we can't. Users have been setting
+	 unsupported DF_1_* flags for a long time and glibc has ignored
+	 them. Therefore to avoid breaking existing applications the
+	 best we can do is add a warning during debugging with the
+	 intent of notifying the user of the problem.  */
+      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)
+	  && l->l_flags_1 & ~DT_1_SUPPORTED_MASK)
+	_dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n",
+			  l->l_flags_1 & ~DT_1_SUPPORTED_MASK);
+
+      if (l->l_flags_1 & DF_1_NOW)
+	info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)];
+    }
+  if (info[DT_RUNPATH] != NULL)
+    /* If both RUNPATH and RPATH are given, the latter is ignored.  */
+    info[DT_RPATH] = NULL;
+#endif
+}
diff --git a/REORG.TODO/elf/global.c b/REORG.TODO/elf/global.c
new file mode 100644
index 0000000000..c675858b64
--- /dev/null
+++ b/REORG.TODO/elf/global.c
@@ -0,0 +1,7 @@
+extern int test (void);
+
+int
+main (void)
+{
+  return test ();
+}
diff --git a/REORG.TODO/elf/globalmod1.c b/REORG.TODO/elf/globalmod1.c
new file mode 100644
index 0000000000..3f80822269
--- /dev/null
+++ b/REORG.TODO/elf/globalmod1.c
@@ -0,0 +1,17 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+extern int test (void);
+
+int
+test (void)
+{
+  (void) dlopen ("reldepmod4.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (dlsym (RTLD_DEFAULT, "call_me") != NULL)
+    {
+      puts ("found \"call_me\"");
+      return 0;
+    }
+  puts ("didn't find \"call_me\"");
+  return 1;
+}
diff --git a/REORG.TODO/elf/ifuncdep1.c b/REORG.TODO/elf/ifuncdep1.c
new file mode 100644
index 0000000000..77d663dcec
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep1.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols without -fPIC.  */
+
+#include "ifuncmod1.c"
diff --git a/REORG.TODO/elf/ifuncdep1pic.c b/REORG.TODO/elf/ifuncdep1pic.c
new file mode 100644
index 0000000000..b6381e4868
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep1pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmod1.c"
diff --git a/REORG.TODO/elf/ifuncdep2.c b/REORG.TODO/elf/ifuncdep2.c
new file mode 100644
index 0000000000..d87d61d5be
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep2.c
@@ -0,0 +1,59 @@
+/* Test 3 STT_GNU_IFUNC symbols.  */
+
+#include "ifunc-sel.h"
+
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+   is fixed.  */
+asm (".protected global");
+
+static int
+one (void)
+{
+  return 1;
+}
+
+static int
+minus_one (void)
+{
+  return -1;
+}
+
+static int
+zero (void)
+{
+  return 0;
+}
+
+void * foo1_ifunc (void) __asm__ ("foo1");
+__asm__(".type foo1, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo1_ifunc (void)
+{
+  return ifunc_sel (one, minus_one, zero);
+}
+
+void * foo2_ifunc (void) __asm__ ("foo2");
+__asm__(".type foo2, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo2_ifunc (void)
+{
+  return ifunc_sel (minus_one, one, zero);
+}
+
+void * foo3_ifunc (void) __asm__ ("foo3");
+__asm__(".type foo3, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo3_ifunc (void)
+{
+  return ifunc_sel (one, zero, minus_one);
+}
diff --git a/REORG.TODO/elf/ifuncdep2pic.c b/REORG.TODO/elf/ifuncdep2pic.c
new file mode 100644
index 0000000000..a84253dbc4
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep2pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncdep2.c"
diff --git a/REORG.TODO/elf/ifuncdep5.c b/REORG.TODO/elf/ifuncdep5.c
new file mode 100644
index 0000000000..f26234336e
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep5.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols without -fPIC.  */
+
+#include "ifuncmod5.c"
diff --git a/REORG.TODO/elf/ifuncdep5pic.c b/REORG.TODO/elf/ifuncdep5pic.c
new file mode 100644
index 0000000000..3edb3a07c6
--- /dev/null
+++ b/REORG.TODO/elf/ifuncdep5pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmod5.c"
diff --git a/REORG.TODO/elf/ifuncmain1.c b/REORG.TODO/elf/ifuncmain1.c
new file mode 100644
index 0000000000..747fc02648
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1.c
@@ -0,0 +1,64 @@
+/* Test STT_GNU_IFUNC symbols:
+
+   1. Direct function call.
+   2. Function pointer.
+   3. Visibility without override.
+ */
+
+#include <stdlib.h>
+
+int ret_foo;
+int ret_foo_hidden;
+int ret_foo_protected;
+
+extern int foo (void);
+extern int foo_protected (void);
+
+#ifndef FOO_P
+typedef int (*foo_p) (void);
+#endif
+
+foo_p foo_ptr = foo;
+foo_p foo_procted_ptr = foo_protected;
+
+extern foo_p get_foo_p (void);
+extern foo_p get_foo_hidden_p (void);
+extern foo_p get_foo_protected_p (void);
+
+int
+main (void)
+{
+  foo_p p;
+
+  if (foo_ptr != foo)
+    abort ();
+  if (foo () != -1)
+    abort ();
+  if ((*foo_ptr) () != -1)
+    abort ();
+
+  if (foo_procted_ptr != foo_protected)
+    abort ();
+  if (foo_protected () != 0)
+    abort ();
+  if ((*foo_procted_ptr) () != 0)
+    abort ();
+
+  p = get_foo_p ();
+  if (p != foo)
+    abort ();
+  if (ret_foo != -1 || (*p) () != ret_foo)
+    abort ();
+
+  p = get_foo_hidden_p ();
+  if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden)
+    abort ();
+
+  p = get_foo_protected_p ();
+  if (p != foo_protected)
+    abort ();
+  if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
+    abort ();
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain1pic.c b/REORG.TODO/elf/ifuncmain1pic.c
new file mode 100644
index 0000000000..db19dc9678
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1picstatic.c b/REORG.TODO/elf/ifuncmain1picstatic.c
new file mode 100644
index 0000000000..c937933029
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1picstatic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and -static.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1pie.c b/REORG.TODO/elf/ifuncmain1pie.c
new file mode 100644
index 0000000000..c16ef6dd09
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1pie.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with PIE.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1static.c b/REORG.TODO/elf/ifuncmain1static.c
new file mode 100644
index 0000000000..fdd1e09024
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1static.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -static.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1staticpic.c b/REORG.TODO/elf/ifuncmain1staticpic.c
new file mode 100644
index 0000000000..39e0cbb4b8
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1staticpic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and no DSO.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1staticpie.c b/REORG.TODO/elf/ifuncmain1staticpie.c
new file mode 100644
index 0000000000..4891114260
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1staticpie.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with PIE and no DSO.  */
+
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain1vis.c b/REORG.TODO/elf/ifuncmain1vis.c
new file mode 100644
index 0000000000..d35e2f81fc
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1vis.c
@@ -0,0 +1,87 @@
+/* Test STT_GNU_IFUNC symbols:
+
+   1. Direct function call.
+   2. Function pointer.
+   3. Visibility with override.
+ */
+
+#include <stdlib.h>
+
+int ret_foo;
+int ret_foo_hidden;
+int ret_foo_protected;
+
+extern int foo (void);
+extern int foo_protected (void);
+
+#ifndef FOO_P
+typedef int (*foo_p) (void);
+#endif
+
+foo_p foo_ptr = foo;
+foo_p foo_procted_ptr = foo_protected;
+
+extern foo_p get_foo_p (void);
+extern foo_p get_foo_hidden_p (void);
+extern foo_p get_foo_protected_p (void);
+
+int
+__attribute__ ((noinline))
+foo (void)
+{
+  return -30;
+}
+
+int
+__attribute__ ((noinline))
+foo_hidden (void)
+{
+  return -20;
+}
+
+int
+__attribute__ ((noinline))
+foo_protected (void)
+{
+  return -40;
+}
+
+int
+main (void)
+{
+  foo_p p;
+
+  if (foo_ptr != foo)
+    abort ();
+  if ((*foo_ptr) () != -30)
+    abort ();
+
+  if (foo_procted_ptr != foo_protected)
+    abort ();
+  if ((*foo_procted_ptr) () != -40)
+    abort ();
+
+  p = get_foo_p ();
+  if (p != foo)
+    abort ();
+  if (foo () != -30)
+    abort ();
+  if (ret_foo != -30 || (*p) () != ret_foo)
+    abort ();
+
+  p = get_foo_hidden_p ();
+  if (foo_hidden () != -20)
+    abort ();
+  if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden)
+    abort ();
+
+  p = get_foo_protected_p ();
+  if (p == foo_protected)
+    abort ();
+  if (foo_protected () != -40)
+    abort ();
+  if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
+    abort ();
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain1vispic.c b/REORG.TODO/elf/ifuncmain1vispic.c
new file mode 100644
index 0000000000..f8c104d560
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1vispic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmain1vis.c"
diff --git a/REORG.TODO/elf/ifuncmain1vispie.c b/REORG.TODO/elf/ifuncmain1vispie.c
new file mode 100644
index 0000000000..ad06d2ba1c
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain1vispie.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with PIE.  */
+
+#include "ifuncmain1vis.c"
diff --git a/REORG.TODO/elf/ifuncmain2.c b/REORG.TODO/elf/ifuncmain2.c
new file mode 100644
index 0000000000..db3ba56a02
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain2.c
@@ -0,0 +1,14 @@
+/* Test calling one STT_GNU_IFUNC function with 3 different
+   STT_GNU_IFUNC definitions.  */
+
+#include <stdlib.h>
+
+extern int foo1 (void);
+
+int
+main (void)
+{
+  if (foo1 () != -1)
+    abort ();
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain2pic.c b/REORG.TODO/elf/ifuncmain2pic.c
new file mode 100644
index 0000000000..0006012a96
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain2pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmain2.c"
diff --git a/REORG.TODO/elf/ifuncmain2picstatic.c b/REORG.TODO/elf/ifuncmain2picstatic.c
new file mode 100644
index 0000000000..3e89db536d
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain2picstatic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and -static.  */
+
+#include "ifuncmain2.c"
diff --git a/REORG.TODO/elf/ifuncmain2static.c b/REORG.TODO/elf/ifuncmain2static.c
new file mode 100644
index 0000000000..6932ae8066
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain2static.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -static.  */
+
+#include "ifuncmain2.c"
diff --git a/REORG.TODO/elf/ifuncmain3.c b/REORG.TODO/elf/ifuncmain3.c
new file mode 100644
index 0000000000..1574dd5cbe
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain3.c
@@ -0,0 +1,129 @@
+/* Test STT_GNU_IFUNC symbols with dlopen:
+
+   1. Direct function call.
+   2. Function pointer.
+   3. Visibility with override.
+ */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef int (*foo_p) (void);
+
+int
+__attribute__ ((noinline))
+foo (void)
+{
+  return -30;
+}
+
+int
+__attribute__ ((noinline))
+foo_hidden (void)
+{
+  return -20;
+}
+
+int
+__attribute__ ((noinline))
+foo_protected (void)
+{
+  return -40;
+}
+
+int
+main (void)
+{
+  foo_p p;
+  foo_p (*f) (void);
+  int *ret;
+
+  void *h = dlopen ("ifuncmod3.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot load: %s\n", dlerror ());
+      return 1;
+    }
+
+  p = dlsym (h, "foo");
+  if (p == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+  if ((*p) () != -1)
+    abort ();
+
+  f = dlsym (h, "get_foo_p");
+  if (f == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  ret = dlsym (h, "ret_foo");
+  if (ret == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  p = (*f) ();
+  if (p != foo)
+    abort ();
+  if (foo () != -30)
+    abort ();
+  if (*ret != -30 || (*p) () != *ret)
+    abort ();
+
+  f = dlsym (h, "get_foo_hidden_p");
+  if (f == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  ret = dlsym (h, "ret_foo_hidden");
+  if (ret == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  p = (*f) ();
+  if (foo_hidden () != -20)
+    abort ();
+  if (*ret != 1 || (*p) () != *ret)
+    abort ();
+
+  f = dlsym (h, "get_foo_protected_p");
+  if (f == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  ret = dlsym (h, "ret_foo_protected");
+  if (ret == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  p = (*f) ();
+  if (p == foo_protected)
+    abort ();
+  if (foo_protected () != -40)
+    abort ();
+  if (*ret != 0 || (*p) () != *ret)
+    abort ();
+
+  if (dlclose (h) != 0)
+    {
+      printf ("cannot close: %s\n", dlerror ());
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain4.c b/REORG.TODO/elf/ifuncmain4.c
new file mode 100644
index 0000000000..e55fee2eb3
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain4.c
@@ -0,0 +1,4 @@
+/* Test STT_GNU_IFUNC symbols in a single source file.  */
+
+#include "ifuncmod1.c"
+#include "ifuncmain1.c"
diff --git a/REORG.TODO/elf/ifuncmain4picstatic.c b/REORG.TODO/elf/ifuncmain4picstatic.c
new file mode 100644
index 0000000000..977d7f97fc
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain4picstatic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and -static.  */
+
+#include "ifuncmain4.c"
diff --git a/REORG.TODO/elf/ifuncmain4static.c b/REORG.TODO/elf/ifuncmain4static.c
new file mode 100644
index 0000000000..c399977013
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain4static.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -static.  */
+
+#include "ifuncmain4.c"
diff --git a/REORG.TODO/elf/ifuncmain5.c b/REORG.TODO/elf/ifuncmain5.c
new file mode 100644
index 0000000000..f398085cb4
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5.c
@@ -0,0 +1,38 @@
+/* Test STT_GNU_IFUNC symbols with dynamic function pointer only.  */
+
+#include <stdlib.h>
+
+extern int foo (void);
+extern int foo_protected (void);
+
+typedef int (*foo_p) (void);
+
+foo_p
+__attribute__ ((noinline))
+get_foo (void)
+{
+  return foo;
+}
+
+foo_p
+__attribute__ ((noinline))
+get_foo_protected (void)
+{
+  return foo_protected;
+}
+
+int
+main (void)
+{
+  foo_p p;
+
+  p = get_foo ();
+  if ((*p) () != -1)
+    abort ();
+
+  p = get_foo_protected ();
+  if ((*p) () != 0)
+    abort ();
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain5pic.c b/REORG.TODO/elf/ifuncmain5pic.c
new file mode 100644
index 0000000000..e9144fbb20
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5pic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC.  */
+
+#include "ifuncmain5.c"
diff --git a/REORG.TODO/elf/ifuncmain5picstatic.c b/REORG.TODO/elf/ifuncmain5picstatic.c
new file mode 100644
index 0000000000..a0afe905d7
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5picstatic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and -static.  */
+
+#include "ifuncmain5.c"
diff --git a/REORG.TODO/elf/ifuncmain5pie.c b/REORG.TODO/elf/ifuncmain5pie.c
new file mode 100644
index 0000000000..669f31eeda
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5pie.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with PIE.  */
+
+#include "ifuncmain5.c"
diff --git a/REORG.TODO/elf/ifuncmain5static.c b/REORG.TODO/elf/ifuncmain5static.c
new file mode 100644
index 0000000000..72504404a5
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5static.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -static.  */
+
+#include "ifuncmain5.c"
diff --git a/REORG.TODO/elf/ifuncmain5staticpic.c b/REORG.TODO/elf/ifuncmain5staticpic.c
new file mode 100644
index 0000000000..9e8bac254f
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain5staticpic.c
@@ -0,0 +1,3 @@
+/* Test STT_GNU_IFUNC symbols with -fPIC and no DSO.  */
+
+#include "ifuncmain5.c"
diff --git a/REORG.TODO/elf/ifuncmain6pie.c b/REORG.TODO/elf/ifuncmain6pie.c
new file mode 100644
index 0000000000..04faeb86ef
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain6pie.c
@@ -0,0 +1,65 @@
+/* Test STT_GNU_IFUNC symbols in PIE:
+
+   1. Direct function call.
+   2. Function pointer.
+   3. Reference from a shared library.
+ */
+
+#include <stdlib.h>
+#include "ifunc-sel.h"
+
+typedef int (*foo_p) (void);
+extern foo_p foo_ptr;
+
+static int
+one (void)
+{
+  return -30;
+}
+
+void * foo_ifunc (void) __asm__ ("foo");
+__asm__(".type foo, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_ifunc (void)
+{
+  return ifunc_one (one);
+}
+
+extern int foo (void);
+extern foo_p get_foo (void);
+extern foo_p get_foo_p (void);
+
+foo_p my_foo_ptr = foo;
+
+int
+main (void)
+{
+  foo_p p;
+
+  p = get_foo ();
+  if (p != foo)
+    abort ();
+  if ((*p) () != -30)
+    abort ();
+
+  p = get_foo_p ();
+  if (p != foo)
+    abort ();
+  if ((*p) () != -30)
+    abort ();
+
+  if (foo_ptr != foo)
+    abort ();
+  if (my_foo_ptr != foo)
+    abort ();
+  if ((*foo_ptr) () != -30)
+    abort ();
+  if ((*my_foo_ptr) () != -30)
+    abort ();
+  if (foo () != -30)
+    abort ();
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain7.c b/REORG.TODO/elf/ifuncmain7.c
new file mode 100644
index 0000000000..1e8f7ea38e
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain7.c
@@ -0,0 +1,72 @@
+/* Test local STT_GNU_IFUNC symbols:
+
+   1. Direct function call.
+   2. Function pointer.
+ */
+
+#include <stdlib.h>
+#include "ifunc-sel.h"
+
+extern int foo (void);
+
+static int
+one (void)
+{
+  return -30;
+}
+
+static void * foo_ifunc (void) __asm__ ("foo");
+__asm__(".type foo, %gnu_indirect_function");
+
+static void *
+__attribute__ ((used))
+inhibit_stack_protector
+foo_ifunc (void)
+{
+  return ifunc_one (one);
+}
+
+typedef int (*foo_p) (void);
+
+foo_p foo_ptr = foo;
+
+foo_p
+__attribute__ ((noinline))
+get_foo_p (void)
+{
+  return foo_ptr;
+}
+
+foo_p
+__attribute__ ((noinline))
+get_foo (void)
+{
+  return foo;
+}
+
+int
+main (void)
+{
+  foo_p p;
+
+  p = get_foo ();
+  if (p != foo)
+    abort ();
+  if ((*p) () != -30)
+    abort ();
+
+  p = get_foo_p ();
+  if (p != foo)
+    abort ();
+  if ((*p) () != -30)
+    abort ();
+
+  if (foo_ptr != foo)
+    abort ();
+  if ((*foo_ptr) () != -30)
+    abort ();
+  if (foo () != -30)
+    abort ();
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ifuncmain7pic.c b/REORG.TODO/elf/ifuncmain7pic.c
new file mode 100644
index 0000000000..fc37bf4469
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain7pic.c
@@ -0,0 +1,7 @@
+/* Test local STT_GNU_IFUNC symbols with -fPIC:
+
+   1. Direct function call.
+   2. Function pointer.
+ */
+
+#include "ifuncmain7.c"
diff --git a/REORG.TODO/elf/ifuncmain7picstatic.c b/REORG.TODO/elf/ifuncmain7picstatic.c
new file mode 100644
index 0000000000..baf8934b95
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain7picstatic.c
@@ -0,0 +1,7 @@
+/* Test local STT_GNU_IFUNC symbols with -fPIC and -static:
+
+   1. Direct function call.
+   2. Function pointer.
+ */
+
+#include "ifuncmain7.c"
diff --git a/REORG.TODO/elf/ifuncmain7pie.c b/REORG.TODO/elf/ifuncmain7pie.c
new file mode 100644
index 0000000000..254d453f1e
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain7pie.c
@@ -0,0 +1,7 @@
+/* Test local STT_GNU_IFUNC symbols with PIE:
+
+   1. Direct function call.
+   2. Function pointer.
+ */
+
+#include "ifuncmain7.c"
diff --git a/REORG.TODO/elf/ifuncmain7static.c b/REORG.TODO/elf/ifuncmain7static.c
new file mode 100644
index 0000000000..e470d570ef
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmain7static.c
@@ -0,0 +1,7 @@
+/* Test local STT_GNU_IFUNC symbols with -static:
+
+   1. Direct function call.
+   2. Function pointer.
+ */
+
+#include "ifuncmain7.c"
diff --git a/REORG.TODO/elf/ifuncmod1.c b/REORG.TODO/elf/ifuncmod1.c
new file mode 100644
index 0000000000..f0bf5fb45f
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmod1.c
@@ -0,0 +1,100 @@
+/* Test STT_GNU_IFUNC symbols:
+
+   1. Direct function call.
+   2. Function pointer.
+   3. Visibility.
+ */
+#include "ifunc-sel.h"
+
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+   is fixed.  */
+asm (".protected global");
+
+static int
+one (void)
+{
+  return 1;
+}
+
+static int
+minus_one (void)
+{
+  return -1;
+}
+
+static int
+zero (void)
+{
+  return 0;
+}
+
+void * foo_ifunc (void) __asm__ ("foo");
+__asm__(".type foo, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_ifunc (void)
+{
+  return ifunc_sel (one, minus_one, zero);
+}
+
+void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
+__asm__(".type foo_hidden, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_hidden_ifunc (void)
+{
+  return ifunc_sel (minus_one, one, zero);
+}
+
+void * foo_protected_ifunc (void) __asm__ ("foo_protected");
+__asm__(".type foo_protected, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_protected_ifunc (void)
+{
+  return ifunc_sel (one, zero, minus_one);
+}
+
+/* Test hidden indirect function.  */
+__asm__(".hidden foo_hidden");
+
+/* Test protected indirect function.  */
+__asm__(".protected foo_protected");
+
+extern int foo (void);
+extern int foo_hidden (void);
+extern int foo_protected (void);
+extern int ret_foo;
+extern int ret_foo_hidden;
+extern int ret_foo_protected;
+
+#define FOO_P
+typedef int (*foo_p) (void);
+
+foo_p
+get_foo_p (void)
+{
+  ret_foo = foo ();
+  return foo;
+}
+
+foo_p
+get_foo_hidden_p (void)
+{
+  ret_foo_hidden = foo_hidden ();
+  return foo_hidden;
+}
+
+foo_p
+get_foo_protected_p (void)
+{
+  ret_foo_protected = foo_protected ();
+  return foo_protected;
+}
diff --git a/REORG.TODO/elf/ifuncmod3.c b/REORG.TODO/elf/ifuncmod3.c
new file mode 100644
index 0000000000..ca2d962600
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmod3.c
@@ -0,0 +1,7 @@
+/* Test STT_GNU_IFUNC symbols with dlopen.  */
+
+#include "ifuncmod1.c"
+
+int ret_foo;
+int ret_foo_hidden;
+int ret_foo_protected;
diff --git a/REORG.TODO/elf/ifuncmod5.c b/REORG.TODO/elf/ifuncmod5.c
new file mode 100644
index 0000000000..5a957800e8
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmod5.c
@@ -0,0 +1,64 @@
+/* Test STT_GNU_IFUNC symbols without direct function call.  */
+#include "ifunc-sel.h"
+
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+   is fixed.  */
+asm (".protected global");
+
+static int
+one (void)
+{
+  return 1;
+}
+
+static int
+minus_one (void)
+{
+  return -1;
+}
+
+static int
+zero (void)
+{
+  return 0;
+}
+
+void * foo_ifunc (void) __asm__ ("foo");
+__asm__(".type foo, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_ifunc (void)
+{
+  return ifunc_sel (one, minus_one, zero);
+}
+
+void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
+__asm__(".type foo_hidden, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_hidden_ifunc (void)
+{
+  return ifunc_sel (minus_one, one, zero);
+}
+
+void * foo_protected_ifunc (void) __asm__ ("foo_protected");
+__asm__(".type foo_protected, %gnu_indirect_function");
+
+void *
+inhibit_stack_protector
+foo_protected_ifunc (void)
+{
+  return ifunc_sel (one, zero, minus_one);
+}
+
+/* Test hidden indirect function.  */
+__asm__(".hidden foo_hidden");
+
+/* Test protected indirect function.  */
+__asm__(".protected foo_protected");
diff --git a/REORG.TODO/elf/ifuncmod6.c b/REORG.TODO/elf/ifuncmod6.c
new file mode 100644
index 0000000000..2e16c1d06d
--- /dev/null
+++ b/REORG.TODO/elf/ifuncmod6.c
@@ -0,0 +1,19 @@
+/* Test STT_GNU_IFUNC symbol reference in a shared library.  */
+
+extern int foo (void);
+
+typedef int (*foo_p) (void);
+
+foo_p foo_ptr = foo;
+
+foo_p
+get_foo_p (void)
+{
+  return foo_ptr;
+}
+
+foo_p
+get_foo (void)
+{
+  return foo;
+}
diff --git a/REORG.TODO/elf/initfirst.c b/REORG.TODO/elf/initfirst.c
new file mode 100644
index 0000000000..5ca83d21bc
--- /dev/null
+++ b/REORG.TODO/elf/initfirst.c
@@ -0,0 +1,22 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *h = dlopen ("firstobj.so", RTLD_LAZY);
+  void *f;
+  if (! h)
+    {
+      printf ("cannot find firstobj.so: %s\n", dlerror ());
+      return 1;
+    }
+  f = dlsym (h, "foo");
+  if (! f)
+    {
+      printf ("cannot find symbol foo: %s\n", dlerror ());
+      return 2;
+    }
+  ((void (*) (void)) f) ();
+  return 0;
+}
diff --git a/REORG.TODO/elf/interp.c b/REORG.TODO/elf/interp.c
new file mode 100644
index 0000000000..b6e8f04444
--- /dev/null
+++ b/REORG.TODO/elf/interp.c
@@ -0,0 +1,22 @@
+/* interp - add information about dynamic loader to shared library objects.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <runtime-linker.h>
+
+const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp")))
+  = RUNTIME_LINKER;
diff --git a/REORG.TODO/elf/lateglobal.c b/REORG.TODO/elf/lateglobal.c
new file mode 100644
index 0000000000..4a1a7cd085
--- /dev/null
+++ b/REORG.TODO/elf/lateglobal.c
@@ -0,0 +1,47 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h[2];
+  int fail;
+  int (*fp) (void);
+
+  mtrace ();
+
+  h[0] = dlopen ("ltglobmod1.so", RTLD_LAZY);
+  if (h[0] == NULL)
+    {
+      printf ("%s: cannot open %s: %s",
+	      __FUNCTION__, "ltglobmod1.so", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+  h[1] = dlopen ("ltglobmod2.so", RTLD_LAZY);
+  if (h[1] == NULL)
+    {
+      printf ("%s: cannot open %s: %s",
+	      __FUNCTION__, "ltglobmod2.so", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  puts ("loaded \"ltglobmod1.so\" without RTLD_GLOBAL");
+
+  fp = dlsym (h[1], "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of `foo': %s", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  fail = fp ();
+
+  puts ("back in main");
+
+  dlclose (h[1]);
+  dlclose (h[0]);
+
+  return fail;
+}
diff --git a/REORG.TODO/elf/ldconfig.c b/REORG.TODO/elf/ldconfig.c
new file mode 100644
index 0000000000..99caf9e9bb
--- /dev/null
+++ b/REORG.TODO/elf/ldconfig.c
@@ -0,0 +1,1418 @@
+/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>, 1999.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#define PROCINFO_CLASS static
+#include <alloca.h>
+#include <argp.h>
+#include <dirent.h>
+#include <elf.h>
+#include <error.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <glob.h>
+#include <libgen.h>
+
+#include <ldconfig.h>
+#include <dl-cache.h>
+
+#include <dl-procinfo.h>
+
+#ifdef _DL_FIRST_PLATFORM
+# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
+#else
+# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
+#endif
+
+#ifndef LD_SO_CONF
+# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
+#endif
+
+/* Get libc version number.  */
+#include <version.h>
+
+#define PACKAGE _libc_intl_domainname
+
+static const struct
+{
+  const char *name;
+  int flag;
+} lib_types[] =
+{
+  {"libc4", FLAG_LIBC4},
+  {"libc5", FLAG_ELF_LIBC5},
+  {"libc6", FLAG_ELF_LIBC6},
+  {"glibc2", FLAG_ELF_LIBC6}
+};
+
+
+/* List of directories to handle.  */
+struct dir_entry
+{
+  char *path;
+  int flag;
+  ino64_t ino;
+  dev_t dev;
+  struct dir_entry *next;
+};
+
+/* The list is unsorted, contains no duplicates.  Entries are added at
+   the end.  */
+static struct dir_entry *dir_entries;
+
+/* Flags for different options.  */
+/* Print Cache.  */
+static int opt_print_cache;
+
+/* Be verbose.  */
+int opt_verbose;
+
+/* Format to support.  */
+/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2.  */
+int opt_format = 1;
+
+/* Build cache.  */
+static int opt_build_cache = 1;
+
+/* Enable symbolic link processing.  If set, create or update symbolic
+   links, and remove stale symbolic links.  */
+static int opt_link = 1;
+
+/* Only process directories specified on the command line.  */
+static int opt_only_cline;
+
+/* Path to root for chroot.  */
+static char *opt_chroot;
+
+/* Manually link given shared libraries.  */
+static int opt_manual_link;
+
+/* Should we ignore an old auxiliary cache file?  */
+static int opt_ignore_aux_cache;
+
+/* Cache file to use.  */
+static char *cache_file;
+
+/* Configuration file.  */
+static const char *config_file;
+
+/* Mask to use for important hardware capabilities.  */
+static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
+
+/* Configuration-defined capabilities defined in kernel vDSOs.  */
+static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *)
+     = print_version;
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
+  { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
+  { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
+  { NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0},
+  { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
+  { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
+  { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
+  { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
+  { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
+  { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
+  { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+#define PROCINFO_CLASS static
+#include <dl-procinfo.c>
+
+/* Short description of program.  */
+static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, NULL, doc, NULL, more_help, NULL
+};
+
+/* Check if string corresponds to an important hardware capability or
+   a platform.  */
+static int
+is_hwcap_platform (const char *name)
+{
+  int hwcap_idx = _dl_string_hwcap (name);
+
+  /* Is this a normal hwcap for the machine like "fpu?"  */
+  if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask))
+    return 1;
+
+  /* Is this a platform pseudo-hwcap like "i686?"  */
+  hwcap_idx = _dl_string_platform (name);
+  if (hwcap_idx != -1)
+    return 1;
+
+  /* Is this one of the extra pseudo-hwcaps that we map beyond
+     _DL_FIRST_EXTRA like "tls", or "nosegneg?"  */
+  for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
+    if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
+	&& !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
+      return 1;
+
+  return 0;
+}
+
+/* Get hwcap (including platform) encoding of path.  */
+static uint64_t
+path_hwcap (const char *path)
+{
+  char *str = xstrdup (path);
+  char *ptr;
+  uint64_t hwcap = 0;
+  uint64_t h;
+
+  size_t len;
+
+  len = strlen (str);
+  if (str[len] == '/')
+    str[len] = '\0';
+
+  /* Search pathname from the end and check for hwcap strings.  */
+  for (;;)
+    {
+      ptr = strrchr (str, '/');
+
+      if (ptr == NULL)
+	break;
+
+      h = _dl_string_hwcap (ptr + 1);
+
+      if (h == (uint64_t) -1)
+	{
+	  h = _dl_string_platform (ptr + 1);
+	  if (h == (uint64_t) -1)
+	    {
+	      for (h = _DL_FIRST_EXTRA; h < 64; ++h)
+		if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
+		    && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
+		  break;
+	      if (h == 64)
+		break;
+	    }
+	}
+      hwcap += 1ULL << h;
+
+      /* Search the next part of the path.  */
+      *ptr = '\0';
+    }
+
+  free (str);
+  return hwcap;
+}
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'C':
+      cache_file = arg;
+      /* Ignore auxiliary cache since we use non-standard cache.  */
+      opt_ignore_aux_cache = 1;
+      break;
+    case 'f':
+      config_file = arg;
+      break;
+    case 'i':
+      opt_ignore_aux_cache = 1;
+      break;
+    case 'l':
+      opt_manual_link = 1;
+      break;
+    case 'N':
+      opt_build_cache = 0;
+      break;
+    case 'n':
+      opt_build_cache = 0;
+      opt_only_cline = 1;
+      break;
+    case 'p':
+      opt_print_cache = 1;
+      break;
+    case 'r':
+      opt_chroot = arg;
+      break;
+    case 'v':
+      opt_verbose = 1;
+      break;
+    case 'X':
+      opt_link = 0;
+      break;
+    case 'c':
+      if (strcmp (arg, "old") == 0)
+	opt_format = 0;
+      else if (strcmp (arg, "compat") == 0)
+	opt_format = 1;
+      else if (strcmp (arg, "new") == 0)
+	opt_format = 2;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+/* Print bug-reporting information in the help message.  */
+static char *
+more_help (int key, const char *text, void *input)
+{
+  char *tp = NULL;
+  switch (key)
+    {
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      if (asprintf (&tp, gettext ("\
+For bug reporting instructions, please see:\n\
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
+    default:
+      break;
+    }
+  return (char *) text;
+}
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "ldconfig %s%s\n", PKGVERSION, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "2017");
+  fprintf (stream, gettext ("Written by %s.\n"),
+	   "Andreas Jaeger");
+}
+
+/* Add a single directory entry.  */
+static void
+add_single_dir (struct dir_entry *entry, int verbose)
+{
+  struct dir_entry *ptr, *prev;
+
+  ptr = dir_entries;
+  prev = ptr;
+  while (ptr != NULL)
+    {
+      /* Check for duplicates.  */
+      if (ptr->ino == entry->ino && ptr->dev == entry->dev)
+	{
+	  if (opt_verbose && verbose)
+	    error (0, 0, _("Path `%s' given more than once"), entry->path);
+	  /* Use the newer information.  */
+	  ptr->flag = entry->flag;
+	  free (entry->path);
+	  free (entry);
+	  break;
+	}
+      prev = ptr;
+      ptr = ptr->next;
+    }
+  /* Is this the first entry?  */
+  if (ptr == NULL && dir_entries == NULL)
+    dir_entries = entry;
+  else if (ptr == NULL)
+    prev->next = entry;
+}
+
+/* Add one directory to the list of directories to process.  */
+static void
+add_dir (const char *line)
+{
+  unsigned int i;
+  struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
+  entry->next = NULL;
+
+  /* Search for an '=' sign.  */
+  entry->path = xstrdup (line);
+  char *equal_sign = strchr (entry->path, '=');
+  if (equal_sign)
+    {
+      *equal_sign = '\0';
+      ++equal_sign;
+      entry->flag = FLAG_ANY;
+      for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
+	if (strcmp (equal_sign, lib_types[i].name) == 0)
+	  {
+	    entry->flag = lib_types[i].flag;
+	    break;
+	  }
+      if (entry->flag == FLAG_ANY)
+	error (0, 0, _("%s is not a known library type"), equal_sign);
+    }
+  else
+    {
+      entry->flag = FLAG_ANY;
+    }
+
+  /* Canonify path: for now only remove leading and trailing
+     whitespace and the trailing slashes.  */
+  i = strlen (entry->path);
+
+  while (i > 0 && isspace (entry->path[i - 1]))
+    entry->path[--i] = '\0';
+
+  while (i > 0 && entry->path[i - 1] == '/')
+    entry->path[--i] = '\0';
+
+  if (i == 0)
+    return;
+
+  char *path = entry->path;
+  if (opt_chroot)
+    path = chroot_canon (opt_chroot, path);
+
+  struct stat64 stat_buf;
+  if (path == NULL || stat64 (path, &stat_buf))
+    {
+      if (opt_verbose)
+	error (0, errno, _("Can't stat %s"), entry->path);
+      free (entry->path);
+      free (entry);
+    }
+  else
+    {
+      entry->ino = stat_buf.st_ino;
+      entry->dev = stat_buf.st_dev;
+
+      add_single_dir (entry, 1);
+    }
+
+  if (opt_chroot)
+    free (path);
+}
+
+
+static int
+chroot_stat (const char *real_path, const char *path, struct stat64 *st)
+{
+  int ret;
+  char *canon_path;
+
+  if (!opt_chroot)
+    return stat64 (real_path, st);
+
+  ret = lstat64 (real_path, st);
+  if (ret || !S_ISLNK (st->st_mode))
+    return ret;
+
+  canon_path = chroot_canon (opt_chroot, path);
+  if (canon_path == NULL)
+    return -1;
+
+  ret = stat64 (canon_path, st);
+  free (canon_path);
+  return ret;
+}
+
+/* Create a symbolic link from soname to libname in directory path.  */
+static void
+create_links (const char *real_path, const char *path, const char *libname,
+	      const char *soname)
+{
+  char *full_libname, *full_soname;
+  char *real_full_libname, *real_full_soname;
+  struct stat64 stat_lib, stat_so, lstat_so;
+  int do_link = 1;
+  int do_remove = 1;
+  /* XXX: The logics in this function should be simplified.  */
+
+  /* Get complete path.  */
+  full_libname = alloca (strlen (path) + strlen (libname) + 2);
+  full_soname = alloca (strlen (path) + strlen (soname) + 2);
+  sprintf (full_libname, "%s/%s", path, libname);
+  sprintf (full_soname, "%s/%s", path, soname);
+  if (opt_chroot)
+    {
+      real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
+      real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
+      sprintf (real_full_libname, "%s/%s", real_path, libname);
+      sprintf (real_full_soname, "%s/%s", real_path, soname);
+    }
+  else
+    {
+      real_full_libname = full_libname;
+      real_full_soname = full_soname;
+    }
+
+  /* Does soname already exist and point to the right library?  */
+  if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
+    {
+      if (chroot_stat (real_full_libname, full_libname, &stat_lib))
+	{
+	  error (0, 0, _("Can't stat %s\n"), full_libname);
+	  return;
+	}
+      if (stat_lib.st_dev == stat_so.st_dev
+	  && stat_lib.st_ino == stat_so.st_ino)
+	/* Link is already correct.  */
+	do_link = 0;
+      else if (lstat64 (full_soname, &lstat_so) == 0
+	       && !S_ISLNK (lstat_so.st_mode))
+	{
+	  error (0, 0, _("%s is not a symbolic link\n"), full_soname);
+	  do_link = 0;
+	  do_remove = 0;
+	}
+    }
+  else if (lstat64 (real_full_soname, &lstat_so) != 0
+	   || !S_ISLNK (lstat_so.st_mode))
+    /* Unless it is a stale symlink, there is no need to remove.  */
+    do_remove = 0;
+
+  if (opt_verbose)
+    printf ("\t%s -> %s", soname, libname);
+
+  if (do_link && opt_link)
+    {
+      /* Remove old link.  */
+      if (do_remove)
+	if (unlink (real_full_soname))
+	  {
+	    error (0, 0, _("Can't unlink %s"), full_soname);
+	    do_link = 0;
+	  }
+      /* Create symbolic link.  */
+      if (do_link && symlink (libname, real_full_soname))
+	{
+	  error (0, 0, _("Can't link %s to %s"), full_soname, libname);
+	  do_link = 0;
+	}
+      if (opt_verbose)
+	{
+	  if (do_link)
+	    fputs (_(" (changed)\n"), stdout);
+	  else
+	    fputs (_(" (SKIPPED)\n"), stdout);
+	}
+    }
+  else if (opt_verbose)
+    fputs ("\n", stdout);
+}
+
+/* Manually link the given library.  */
+static void
+manual_link (char *library)
+{
+  char *path;
+  char *real_path;
+  char *real_library;
+  char *libname;
+  char *soname;
+  struct stat64 stat_buf;
+  int flag;
+  unsigned int osversion;
+
+  /* Prepare arguments for create_links call.  Split library name in
+     directory and filename first.  Since path is allocated, we've got
+     to be careful to free at the end.  */
+  path = xstrdup (library);
+  libname = strrchr (path, '/');
+
+  if (libname)
+    {
+      /* Successfully split names.  Check if path is just "/" to avoid
+	 an empty path.  */
+      if (libname == path)
+	{
+	  libname = library + 1;
+	  path = xrealloc (path, 2);
+	  strcpy (path, "/");
+	}
+      else
+	{
+	  *libname = '\0';
+	  ++libname;
+	}
+    }
+  else
+    {
+      /* There's no path, construct one. */
+      libname = library;
+      path = xrealloc (path, 2);
+      strcpy (path, ".");
+    }
+
+  if (opt_chroot)
+    {
+      real_path = chroot_canon (opt_chroot, path);
+      if (real_path == NULL)
+	{
+	  error (0, errno, _("Can't find %s"), path);
+	  free (path);
+	  return;
+	}
+      real_library = alloca (strlen (real_path) + strlen (libname) + 2);
+      sprintf (real_library, "%s/%s", real_path, libname);
+    }
+  else
+    {
+      real_path = path;
+      real_library = library;
+    }
+
+  /* Do some sanity checks first.  */
+  if (lstat64 (real_library, &stat_buf))
+    {
+      error (0, errno, _("Cannot lstat %s"), library);
+      free (path);
+      return;
+    }
+  /* We don't want links here!  */
+  else if (!S_ISREG (stat_buf.st_mode))
+    {
+      error (0, 0, _("Ignored file %s since it is not a regular file."),
+	     library);
+      free (path);
+      return;
+    }
+
+  if (process_file (real_library, library, libname, &flag, &osversion,
+		    &soname, 0, &stat_buf))
+    {
+      error (0, 0, _("No link created since soname could not be found for %s"),
+	     library);
+      free (path);
+      return;
+    }
+  if (soname == NULL)
+    soname = implicit_soname (libname, flag);
+  create_links (real_path, path, libname, soname);
+  free (soname);
+  free (path);
+}
+
+
+/* Read a whole directory and search for libraries.
+   The purpose is two-fold:
+   - search for libraries which will be added to the cache
+   - create symbolic links to the soname for each library
+
+   This has to be done separatly for each directory.
+
+   To keep track of which libraries to add to the cache and which
+   links to create, we save a list of all libraries.
+
+   The algorithm is basically:
+   for all libraries in the directory do
+     get soname of library
+     if soname is already in list
+       if new library is newer, replace entry
+       otherwise ignore this library
+     otherwise add library to list
+
+   For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
+   exist and both have the same soname, e.g. libxy.so, a symbolic link
+   is created from libxy.so.1.2 (the newer one) to libxy.so.
+   libxy.so.1.2 and libxy.so are added to the cache - but not
+   libxy.so.1.1.  */
+
+/* Information for one library.  */
+struct dlib_entry
+{
+  char *name;
+  char *soname;
+  int flag;
+  int is_link;
+  unsigned int osversion;
+  struct dlib_entry *next;
+};
+
+
+static void
+search_dir (const struct dir_entry *entry)
+{
+  uint64_t hwcap = path_hwcap (entry->path);
+  if (opt_verbose)
+    {
+      if (hwcap != 0)
+	printf ("%s: (hwcap: %#.16" PRIx64 ")\n", entry->path, hwcap);
+      else
+	printf ("%s:\n", entry->path);
+    }
+
+  char *dir_name;
+  char *real_file_name;
+  size_t real_file_name_len;
+  size_t file_name_len = PATH_MAX;
+  char *file_name = alloca (file_name_len);
+  if (opt_chroot)
+    {
+      dir_name = chroot_canon (opt_chroot, entry->path);
+      real_file_name_len = PATH_MAX;
+      real_file_name = alloca (real_file_name_len);
+    }
+  else
+    {
+      dir_name = entry->path;
+      real_file_name_len = 0;
+      real_file_name = file_name;
+    }
+
+  DIR *dir;
+  if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
+    {
+      if (opt_verbose)
+	error (0, errno, _("Can't open directory %s"), entry->path);
+      if (opt_chroot && dir_name)
+	free (dir_name);
+      return;
+    }
+
+  struct dirent64 *direntry;
+  struct dlib_entry *dlibs = NULL;
+  while ((direntry = readdir64 (dir)) != NULL)
+    {
+      int flag;
+#ifdef _DIRENT_HAVE_D_TYPE
+      /* We only look at links and regular files.  */
+      if (direntry->d_type != DT_UNKNOWN
+	  && direntry->d_type != DT_LNK
+	  && direntry->d_type != DT_REG
+	  && direntry->d_type != DT_DIR)
+	continue;
+#endif /* _DIRENT_HAVE_D_TYPE  */
+      /* Does this file look like a shared library or is it a hwcap
+	 subdirectory?  The dynamic linker is also considered as
+	 shared library.  */
+      if (((strncmp (direntry->d_name, "lib", 3) != 0
+	    && strncmp (direntry->d_name, "ld-", 3) != 0)
+	   || strstr (direntry->d_name, ".so") == NULL)
+	  && (
+#ifdef _DIRENT_HAVE_D_TYPE
+	      direntry->d_type == DT_REG ||
+#endif
+	      !is_hwcap_platform (direntry->d_name)))
+	continue;
+
+      size_t len = strlen (direntry->d_name);
+      /* Skip temporary files created by the prelink program.  Files with
+	 names like these are never really DSOs we want to look at.  */
+      if (len >= sizeof (".#prelink#") - 1)
+	{
+	  if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1,
+		      ".#prelink#") == 0)
+	    continue;
+	  if (len >= sizeof (".#prelink#.XXXXXX") - 1
+	      && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
+			 + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
+	    continue;
+	}
+      len += strlen (entry->path) + 2;
+      if (len > file_name_len)
+	{
+	  file_name_len = len;
+	  file_name = alloca (file_name_len);
+	  if (!opt_chroot)
+	    real_file_name = file_name;
+	}
+      sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
+      if (opt_chroot)
+	{
+	  len = strlen (dir_name) + strlen (direntry->d_name) + 2;
+	  if (len > real_file_name_len)
+	    {
+	      real_file_name_len = len;
+	      real_file_name = alloca (real_file_name_len);
+	    }
+	  sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
+	}
+
+      struct stat64 lstat_buf;
+#ifdef _DIRENT_HAVE_D_TYPE
+      /* We optimize and try to do the lstat call only if needed.  */
+      if (direntry->d_type != DT_UNKNOWN)
+	lstat_buf.st_mode = DTTOIF (direntry->d_type);
+      else
+#endif
+	if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf)))
+	  {
+	    error (0, errno, _("Cannot lstat %s"), file_name);
+	    continue;
+	  }
+
+      struct stat64 stat_buf;
+      int is_dir;
+      int is_link = S_ISLNK (lstat_buf.st_mode);
+      if (is_link)
+	{
+	  /* In case of symlink, we check if the symlink refers to
+	     a directory. */
+	  char *target_name = real_file_name;
+	  if (opt_chroot)
+	    {
+	      target_name = chroot_canon (opt_chroot, file_name);
+	      if (target_name == NULL)
+		{
+		  if (strstr (file_name, ".so") == NULL)
+		    error (0, 0, _("Input file %s not found.\n"), file_name);
+		  continue;
+		}
+	    }
+	  if (__glibc_unlikely (stat64 (target_name, &stat_buf)))
+	    {
+	      if (opt_verbose)
+		error (0, errno, _("Cannot stat %s"), file_name);
+
+	      /* Remove stale symlinks.  */
+	      if (opt_link && strstr (direntry->d_name, ".so."))
+		unlink (real_file_name);
+	      continue;
+	    }
+	  is_dir = S_ISDIR (stat_buf.st_mode);
+
+	  /* lstat_buf is later stored, update contents.  */
+	  lstat_buf.st_dev = stat_buf.st_dev;
+	  lstat_buf.st_ino = stat_buf.st_ino;
+	  lstat_buf.st_size = stat_buf.st_size;
+	  lstat_buf.st_ctime = stat_buf.st_ctime;
+	}
+      else
+	is_dir = S_ISDIR (lstat_buf.st_mode);
+
+      if (is_dir && is_hwcap_platform (direntry->d_name))
+	{
+	  /* Handle subdirectory later.  */
+	  struct dir_entry *new_entry;
+
+	  new_entry = xmalloc (sizeof (struct dir_entry));
+	  new_entry->path = xstrdup (file_name);
+	  new_entry->flag = entry->flag;
+	  new_entry->next = NULL;
+#ifdef _DIRENT_HAVE_D_TYPE
+	  /* We have filled in lstat only #ifndef
+	     _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
+	  if (!is_link
+	      && direntry->d_type != DT_UNKNOWN
+	      && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
+	    {
+	      error (0, errno, _("Cannot lstat %s"), file_name);
+	      free (new_entry->path);
+	      free (new_entry);
+	      continue;
+	    }
+#endif
+	  new_entry->ino = lstat_buf.st_ino;
+	  new_entry->dev = lstat_buf.st_dev;
+	  add_single_dir (new_entry, 0);
+	  continue;
+	}
+      else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
+	continue;
+
+      char *real_name;
+      if (opt_chroot && is_link)
+	{
+	  real_name = chroot_canon (opt_chroot, file_name);
+	  if (real_name == NULL)
+	    {
+	      if (strstr (file_name, ".so") == NULL)
+		error (0, 0, _("Input file %s not found.\n"), file_name);
+	      continue;
+	    }
+	}
+      else
+	real_name = real_file_name;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+      /* Call lstat64 if not done yet.  */
+      if (!is_link
+	  && direntry->d_type != DT_UNKNOWN
+	  && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
+	{
+	  error (0, errno, _("Cannot lstat %s"), file_name);
+	  continue;
+	}
+#endif
+
+      /* First search whether the auxiliary cache contains this
+	 library already and it's not changed.  */
+      char *soname;
+      unsigned int osversion;
+      if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname))
+	{
+	  if (process_file (real_name, file_name, direntry->d_name, &flag,
+			    &osversion, &soname, is_link, &lstat_buf))
+	    {
+	      if (real_name != real_file_name)
+		free (real_name);
+	      continue;
+	    }
+	  else if (opt_build_cache)
+	    add_to_aux_cache (&lstat_buf, flag, osversion, soname);
+	}
+
+      if (soname == NULL)
+	soname = implicit_soname (direntry->d_name, flag);
+
+      /* A link may just point to itself.  */
+      if (is_link)
+	{
+	  /* If the path the link points to isn't its soname or it is not
+	     the .so symlink for ld(1), we treat it as a normal file.
+
+	     You should always do this:
+
+		libfoo.so -> SONAME -> Arbitrary package-chosen name.
+
+	     e.g. libfoo.so -> libfoo.so.1 -> libfooimp.so.9.99.
+	     Given a SONAME of libfoo.so.1.
+
+	     You should *never* do this:
+
+		libfoo.so -> libfooimp.so.9.99
+
+	     If you do, and your SONAME is libfoo.so.1, then libfoo.so
+	     fails to point at the SONAME. In that case ldconfig may consider
+	     libfoo.so as another implementation of SONAME and will create
+	     symlinks against it causing problems when you try to upgrade
+	     or downgrade. The problems will arise because ldconfig will,
+	     depending on directory ordering, creat symlinks against libfoo.so
+	     e.g. libfoo.so.1.2 -> libfoo.so, but when libfoo.so is removed
+	     (typically by the removal of a development pacakge not required
+	     for the runtime) it will break the libfoo.so.1.2 symlink and the
+	     application will fail to start.  */
+	  const char *real_base_name = basename (real_file_name);
+
+	  if (strcmp (real_base_name, soname) != 0)
+	    {
+	      len = strlen (real_base_name);
+	      if (len < strlen (".so")
+		  || strcmp (real_base_name + len - strlen (".so"), ".so") != 0
+		  || strncmp (real_base_name, soname, len) != 0)
+		is_link = 0;
+	    }
+	}
+
+      if (real_name != real_file_name)
+	free (real_name);
+
+      if (is_link)
+	{
+	  free (soname);
+	  soname = xstrdup (direntry->d_name);
+	}
+
+      if (flag == FLAG_ELF
+	  && (entry->flag == FLAG_ELF_LIBC5
+	      || entry->flag == FLAG_ELF_LIBC6))
+	flag = entry->flag;
+
+      /* Some sanity checks to print warnings.  */
+      if (opt_verbose)
+	{
+	  if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
+	      && entry->flag != FLAG_ANY)
+	    error (0, 0, _("libc5 library %s in wrong directory"), file_name);
+	  if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
+	      && entry->flag != FLAG_ANY)
+	    error (0, 0, _("libc6 library %s in wrong directory"), file_name);
+	  if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
+	      && entry->flag != FLAG_ANY)
+	    error (0, 0, _("libc4 library %s in wrong directory"), file_name);
+	}
+
+      /* Add library to list.  */
+      struct dlib_entry *dlib_ptr;
+      for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
+	{
+	  /* Is soname already in list?  */
+	  if (strcmp (dlib_ptr->soname, soname) == 0)
+	    {
+	      /* Prefer a file to a link, otherwise check which one
+		 is newer.  */
+	      if ((!is_link && dlib_ptr->is_link)
+		  || (is_link == dlib_ptr->is_link
+		      && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
+		{
+		  /* It's newer - add it.  */
+		  /* Flag should be the same - sanity check.  */
+		  if (dlib_ptr->flag != flag)
+		    {
+		      if (dlib_ptr->flag == FLAG_ELF
+			  && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
+			dlib_ptr->flag = flag;
+		      else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
+				|| dlib_ptr->flag == FLAG_ELF_LIBC6)
+			       && flag == FLAG_ELF)
+			dlib_ptr->flag = flag;
+		      else
+			error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
+			       dlib_ptr->name, direntry->d_name,
+			       entry->path);
+		    }
+		  free (dlib_ptr->name);
+		  dlib_ptr->name = xstrdup (direntry->d_name);
+		  dlib_ptr->is_link = is_link;
+		  dlib_ptr->osversion = osversion;
+		}
+	      /* Don't add this library, abort loop.  */
+	      /* Also free soname, since it's dynamically allocated.  */
+	      free (soname);
+	      break;
+	    }
+	}
+      /* Add the library if it's not already in.  */
+      if (dlib_ptr == NULL)
+	{
+	  dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
+	  dlib_ptr->name = xstrdup (direntry->d_name);
+	  dlib_ptr->soname = soname;
+	  dlib_ptr->flag = flag;
+	  dlib_ptr->is_link = is_link;
+	  dlib_ptr->osversion = osversion;
+	  /* Add at head of list.  */
+	  dlib_ptr->next = dlibs;
+	  dlibs = dlib_ptr;
+	}
+    }
+
+  closedir (dir);
+
+  /* Now dlibs contains a list of all libs - add those to the cache
+     and created all symbolic links.  */
+  struct dlib_entry *dlib_ptr;
+  for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
+    {
+      /* Don't create links to links.  */
+      if (dlib_ptr->is_link == 0)
+	create_links (dir_name, entry->path, dlib_ptr->name,
+		      dlib_ptr->soname);
+      if (opt_build_cache)
+	add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
+		      dlib_ptr->osversion, hwcap);
+    }
+
+  /* Free all resources.  */
+  while (dlibs)
+    {
+      dlib_ptr = dlibs;
+      free (dlib_ptr->soname);
+      free (dlib_ptr->name);
+      dlibs = dlibs->next;
+      free (dlib_ptr);
+    }
+
+  if (opt_chroot && dir_name)
+    free (dir_name);
+}
+
+/* Search through all libraries.  */
+static void
+search_dirs (void)
+{
+  struct dir_entry *entry;
+
+  for (entry = dir_entries; entry != NULL; entry = entry->next)
+    search_dir (entry);
+
+  /* Free all allocated memory.  */
+  while (dir_entries)
+    {
+      entry = dir_entries;
+      dir_entries = dir_entries->next;
+      free (entry->path);
+      free (entry);
+    }
+}
+
+
+static void parse_conf_include (const char *config_file, unsigned int lineno,
+				bool do_chroot, const char *pattern);
+
+/* Parse configuration file.  */
+static void
+parse_conf (const char *filename, bool do_chroot)
+{
+  FILE *file = NULL;
+  char *line = NULL;
+  const char *canon;
+  size_t len = 0;
+  unsigned int lineno;
+
+  if (do_chroot && opt_chroot)
+    {
+      canon = chroot_canon (opt_chroot, filename);
+      if (canon)
+	file = fopen (canon, "r");
+      else
+	canon = filename;
+    }
+  else
+    {
+      canon = filename;
+      file = fopen (filename, "r");
+    }
+
+  if (file == NULL)
+    {
+      error (0, errno, _("\
+Warning: ignoring configuration file that cannot be opened: %s"),
+	     canon);
+      if (canon != filename)
+	free ((char *) canon);
+      return;
+    }
+
+  /* No threads use this stream.  */
+  __fsetlocking (file, FSETLOCKING_BYCALLER);
+
+  if (canon != filename)
+    free ((char *) canon);
+
+  lineno = 0;
+  do
+    {
+      ssize_t n = getline (&line, &len, file);
+      if (n < 0)
+	break;
+
+      ++lineno;
+      if (line[n - 1] == '\n')
+	line[n - 1] = '\0';
+
+      /* Because the file format does not know any form of quoting we
+	 can search forward for the next '#' character and if found
+	 make it terminating the line.  */
+      *strchrnul (line, '#') = '\0';
+
+      /* Remove leading whitespace.  NUL is no whitespace character.  */
+      char *cp = line;
+      while (isspace (*cp))
+	++cp;
+
+      /* If the line is blank it is ignored.  */
+      if (cp[0] == '\0')
+	continue;
+
+      if (!strncmp (cp, "include", 7) && isblank (cp[7]))
+	{
+	  char *dir;
+	  cp += 8;
+	  while ((dir = strsep (&cp, " \t")) != NULL)
+	    if (dir[0] != '\0')
+	      parse_conf_include (filename, lineno, do_chroot, dir);
+	}
+      else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5]))
+	{
+	  cp += 6;
+	  char *p, *name = NULL;
+	  unsigned long int n = strtoul (cp, &cp, 0);
+	  if (cp != NULL && isblank (*cp))
+	    while ((p = strsep (&cp, " \t")) != NULL)
+	      if (p[0] != '\0')
+		{
+		  if (name == NULL)
+		    name = p;
+		  else
+		    {
+		      name = NULL;
+		      break;
+		    }
+		}
+	  if (name == NULL)
+	    {
+	      error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"),
+		     filename, lineno);
+	      break;
+	    }
+	  if (n >= (64 - _DL_FIRST_EXTRA))
+	    error (EXIT_FAILURE, 0,
+		   _("%s:%u: hwcap index %lu above maximum %u"),
+		   filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1);
+	  if (hwcap_extra[n] == NULL)
+	    {
+	      for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h)
+		if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h]))
+		  error (EXIT_FAILURE, 0,
+			 _("%s:%u: hwcap index %lu already defined as %s"),
+			 filename, lineno, h, name);
+	      hwcap_extra[n] = xstrdup (name);
+	    }
+	  else
+	    {
+	      if (strcmp (name, hwcap_extra[n]))
+		error (EXIT_FAILURE, 0,
+		       _("%s:%u: hwcap index %lu already defined as %s"),
+		       filename, lineno, n, hwcap_extra[n]);
+	      if (opt_verbose)
+		error (0, 0, _("%s:%u: duplicate hwcap %lu %s"),
+		       filename, lineno, n, name);
+	    }
+	}
+      else
+	add_dir (cp);
+    }
+  while (!feof_unlocked (file));
+
+  /* Free buffer and close file.  */
+  free (line);
+  fclose (file);
+}
+
+/* Handle one word in an `include' line, a glob pattern of additional
+   config files to read.  */
+static void
+parse_conf_include (const char *config_file, unsigned int lineno,
+		    bool do_chroot, const char *pattern)
+{
+  if (opt_chroot && pattern[0] != '/')
+    error (EXIT_FAILURE, 0,
+	   _("need absolute file name for configuration file when using -r"));
+
+  char *copy = NULL;
+  if (pattern[0] != '/' && strchr (config_file, '/') != NULL)
+    {
+      if (asprintf (&copy, "%s/%s", dirname (strdupa (config_file)),
+		    pattern) < 0)
+	error (EXIT_FAILURE, 0, _("memory exhausted"));
+      pattern = copy;
+    }
+
+  glob64_t gl;
+  int result;
+  if (do_chroot && opt_chroot)
+    {
+      char *canon = chroot_canon (opt_chroot, pattern);
+      if (canon == NULL)
+	return;
+      result = glob64 (canon, 0, NULL, &gl);
+      free (canon);
+    }
+  else
+    result = glob64 (pattern, 0, NULL, &gl);
+
+  switch (result)
+    {
+    case 0:
+      for (size_t i = 0; i < gl.gl_pathc; ++i)
+	parse_conf (gl.gl_pathv[i], false);
+      globfree64 (&gl);
+      break;
+
+    case GLOB_NOMATCH:
+      break;
+
+    case GLOB_NOSPACE:
+      errno = ENOMEM;
+    case GLOB_ABORTED:
+      if (opt_verbose)
+	error (0, errno, _("%s:%u: cannot read directory %s"),
+	       config_file, lineno, pattern);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+
+  free (copy);
+}
+
+/* Honour LD_HWCAP_MASK.  */
+static void
+set_hwcap (void)
+{
+  char *mask = getenv ("LD_HWCAP_MASK");
+
+  if (mask)
+    hwcap_mask = strtoul (mask, NULL, 0);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  /* Set locale via LC_ALL.  */
+  setlocale (LC_ALL, "");
+
+  /* Set the text message domain.  */
+  textdomain (_libc_intl_domainname);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Remaining arguments are additional directories if opt_manual_link
+     is not set.  */
+  if (remaining != argc && !opt_manual_link)
+    {
+      int i;
+      for (i = remaining; i < argc; ++i)
+	if (opt_build_cache && argv[i][0] != '/')
+	  error (EXIT_FAILURE, 0,
+		 _("relative path `%s' used to build cache"),
+		 argv[i]);
+	else
+	  add_dir (argv[i]);
+    }
+
+  /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which
+     indicates support for TLS.  This pseudo-hwcap is only used by old versions
+     under which TLS support was optional.  The entry is no longer needed, but
+     must remain for compatibility.  */
+  hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
+
+  set_hwcap ();
+
+  if (opt_chroot)
+    {
+      /* Normalize the path a bit, we might need it for printing later.  */
+      char *endp = rawmemchr (opt_chroot, '\0');
+      while (endp > opt_chroot && endp[-1] == '/')
+	--endp;
+      *endp = '\0';
+      if (endp == opt_chroot)
+	opt_chroot = NULL;
+
+      if (opt_chroot)
+	{
+	  /* It is faster to use chroot if we can.  */
+	  if (!chroot (opt_chroot))
+	    {
+	      if (chdir ("/"))
+		error (EXIT_FAILURE, errno, _("Can't chdir to /"));
+	      opt_chroot = NULL;
+	    }
+	}
+    }
+
+  if (cache_file == NULL)
+    {
+      cache_file = alloca (strlen (LD_SO_CACHE) + 1);
+      strcpy (cache_file, LD_SO_CACHE);
+    }
+
+  if (config_file == NULL)
+    config_file = LD_SO_CONF;
+
+  if (opt_print_cache)
+    {
+      if (opt_chroot)
+	{
+	  char *p = chroot_canon (opt_chroot, cache_file);
+	  if (p == NULL)
+	    error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
+		   cache_file);
+	  cache_file = p;
+	}
+      print_cache (cache_file);
+      if (opt_chroot)
+	free (cache_file);
+      exit (0);
+    }
+
+  if (opt_chroot)
+    {
+      /* Canonicalize the directory name of cache_file, not cache_file,
+	 because we'll rename a temporary cache file to it.  */
+      char *p = strrchr (cache_file, '/');
+      char *canon = chroot_canon (opt_chroot,
+				  p ? (*p = '\0', cache_file) : "/");
+
+      if (canon == NULL)
+	error (EXIT_FAILURE, errno,
+	       _("Can't open cache file directory %s\n"),
+	       p ? cache_file : "/");
+
+      if (p)
+	++p;
+      else
+	p = cache_file;
+
+      cache_file = alloca (strlen (canon) + strlen (p) + 2);
+      sprintf (cache_file, "%s/%s", canon, p);
+      free (canon);
+    }
+
+  if (opt_manual_link)
+    {
+      /* Link all given libraries manually.  */
+      int i;
+
+      for (i = remaining; i < argc; ++i)
+	manual_link (argv[i]);
+
+      exit (0);
+    }
+
+
+  if (opt_build_cache)
+    init_cache ();
+
+  if (!opt_only_cline)
+    {
+      parse_conf (config_file, true);
+
+      /* Always add the standard search paths.  */
+      add_system_dir (SLIBDIR);
+      if (strcmp (SLIBDIR, LIBDIR))
+	add_system_dir (LIBDIR);
+    }
+
+  const char *aux_cache_file = _PATH_LDCONFIG_AUX_CACHE;
+  if (opt_chroot)
+    aux_cache_file = chroot_canon (opt_chroot, aux_cache_file);
+
+  if (! opt_ignore_aux_cache && aux_cache_file)
+    load_aux_cache (aux_cache_file);
+  else
+    init_aux_cache ();
+
+  search_dirs ();
+
+  if (opt_build_cache)
+    {
+      save_cache (cache_file);
+      if (aux_cache_file)
+	save_aux_cache (aux_cache_file);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/ldd.bash.in b/REORG.TODO/elf/ldd.bash.in
new file mode 100644
index 0000000000..7dd1fccf24
--- /dev/null
+++ b/REORG.TODO/elf/ldd.bash.in
@@ -0,0 +1,203 @@
+#! @BASH@
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+
+# This is the `ldd' command, which lists what shared libraries are
+# used by given dynamically-linked executables.  It works by invoking the
+# run-time dynamic linker as a command and setting the environment
+# variable LD_TRACE_LOADED_OBJECTS to a non-empty value.
+
+# We should be able to find the translation right at the beginning.
+TEXTDOMAIN=libc
+TEXTDOMAINDIR=@TEXTDOMAINDIR@
+
+RTLDLIST=@RTLD@
+warn=
+bind_now=
+verbose=
+
+while test $# -gt 0; do
+  case "$1" in
+  --vers | --versi | --versio | --version)
+    echo 'ldd @PKGVERSION@@VERSION@'
+    printf $"Copyright (C) %s Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+" "2017"
+    printf $"Written by %s and %s.
+" "Roland McGrath" "Ulrich Drepper"
+    exit 0
+    ;;
+  --h | --he | --hel | --help)
+    echo $"Usage: ldd [OPTION]... FILE...
+      --help              print this help and exit
+      --version           print version information and exit
+  -d, --data-relocs       process data relocations
+  -r, --function-relocs   process data and function relocations
+  -u, --unused            print unused direct dependencies
+  -v, --verbose           print all information
+"
+    printf $"For bug reporting instructions, please see:\\n%s.\\n" \
+      "@REPORT_BUGS_TO@"
+    exit 0
+    ;;
+  -d | --d | --da | --dat | --data | --data- | --data-r | --data-re | \
+  --data-rel | --data-relo | --data-reloc | --data-relocs)
+    warn=yes
+    shift
+    ;;
+  -r | --f | --fu | --fun | --func | --funct | --functi | --functio | \
+  --function | --function- | --function-r | --function-re | --function-rel | \
+  --function-relo | --function-reloc | --function-relocs)
+    warn=yes
+    bind_now=yes
+    shift
+    ;;
+  -v | --verb | --verbo | --verbos | --verbose)
+    verbose=yes
+    shift
+    ;;
+  -u | --u | --un | --unu | --unus | --unuse | --unused)
+    unused=yes
+    shift
+    ;;
+  --v | --ve | --ver)
+    echo >&2 $"ldd: option \`$1' is ambiguous"
+    exit 1
+    ;;
+  --)		# Stop option processing.
+    shift; break
+    ;;
+  -*)
+    echo >&2 'ldd:' $"unrecognized option" "\`$1'"
+    echo >&2 $"Try \`ldd --help' for more information."
+    exit 1
+    ;;
+  *)
+    break
+    ;;
+  esac
+done
+
+nonelf ()
+{
+  # Maybe extra code for non-ELF binaries.
+  return 1;
+}
+
+add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now"
+add_env="$add_env LD_VERBOSE=$verbose"
+if test "$unused" = yes; then
+  add_env="$add_env LD_DEBUG=\"$LD_DEBUG${LD_DEBUG:+,}unused\""
+fi
+
+# The following command substitution is needed to make ldd work in SELinux
+# environments where the RTLD might not have permission to write to the
+# terminal.  The extra "x" character prevents the shell from trimming trailing
+# newlines from command substitution results.  This function is defined as a
+# subshell compound list (using "(...)") to prevent parameter assignments from
+# affecting the calling shell execution environment.
+try_trace() (
+  output=$(eval $add_env '"$@"' 2>&1; rc=$?; printf 'x'; exit $rc)
+  rc=$?
+  printf '%s' "${output%x}"
+  return $rc
+)
+
+case $# in
+0)
+  echo >&2 'ldd:' $"missing file arguments"
+  echo >&2 $"Try \`ldd --help' for more information."
+  exit 1
+  ;;
+1)
+  single_file=t
+  ;;
+*)
+  single_file=f
+  ;;
+esac
+
+result=0
+for file do
+  # We don't list the file name when there is only one.
+  test $single_file = t || echo "${file}:"
+  case $file in
+  */*) :
+       ;;
+  *) file=./$file
+     ;;
+  esac
+  if test ! -e "$file"; then
+    echo "ldd: ${file}:" $"No such file or directory" >&2
+    result=1
+  elif test ! -f "$file"; then
+    echo "ldd: ${file}:" $"not regular file" >&2
+    result=1
+  elif test -r "$file"; then
+    test -x "$file" || echo 'ldd:' $"\
+warning: you do not have execution permission for" "\`$file'" >&2
+    RTLD=
+    ret=1
+    for rtld in ${RTLDLIST}; do
+      if test -x $rtld; then
+	verify_out=`${rtld} --verify "$file"`
+	ret=$?
+	case $ret in
+	[02]) RTLD=${rtld}; break;;
+	esac
+      fi
+    done
+    case $ret in
+    0)
+      # If the program exits with exit code 5, it means the process has been
+      # invoked with __libc_enable_secure.  Fall back to running it through
+      # the dynamic linker.
+      try_trace "$file"
+      rc=$?
+      if [ $rc = 5 ]; then
+	try_trace "$RTLD" "$file"
+	rc=$?
+      fi
+      [ $rc = 0 ] || result=1
+      ;;
+    1)
+      # This can be a non-ELF binary or no binary at all.
+      nonelf "$file" || {
+	echo $"	not a dynamic executable"
+	result=1
+      }
+      ;;
+    2)
+      try_trace "$RTLD" "$file" || result=1
+      ;;
+    *)
+      echo 'ldd:' ${RTLD} $"exited with unknown exit code" "($ret)" >&2
+      exit 1
+      ;;
+    esac
+  else
+    echo 'ldd:' $"error: you do not have read permission for" "\`$file'" >&2
+    result=1
+  fi
+done
+
+exit $result
+# Local Variables:
+#  mode:ksh
+# End:
diff --git a/REORG.TODO/elf/link.h b/REORG.TODO/elf/link.h
new file mode 100644
index 0000000000..0e223ce9f0
--- /dev/null
+++ b/REORG.TODO/elf/link.h
@@ -0,0 +1,194 @@
+/* Data structure for communication from the run-time dynamic linker for
+   loaded ELF shared objects.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_LINK_H
+#define	_LINK_H	1
+
+#include <features.h>
+#include <elf.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+
+/* We use this macro to refer to ELF types independent of the native wordsize.
+   `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'.  */
+#define ElfW(type)	_ElfW (Elf, __ELF_NATIVE_CLASS, type)
+#define _ElfW(e,w,t)	_ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t)	e##w##t
+
+#include <bits/elfclass.h>		/* Defines __ELF_NATIVE_CLASS.  */
+#include <bits/link.h>
+
+/* Rendezvous structure used by the run-time dynamic linker to communicate
+   details of shared object loading to the debugger.  If the executable's
+   dynamic section has a DT_DEBUG element, the run-time linker sets that
+   element's value to the address where this structure can be found.  */
+
+struct r_debug
+  {
+    int r_version;		/* Version number for this protocol.  */
+
+    struct link_map *r_map;	/* Head of the chain of loaded objects.  */
+
+    /* This is the address of a function internal to the run-time linker,
+       that will always be called when the linker begins to map in a
+       library or unmap it, and again when the mapping change is complete.
+       The debugger can set a breakpoint at this address if it wants to
+       notice shared object mapping changes.  */
+    ElfW(Addr) r_brk;
+    enum
+      {
+	/* This state value describes the mapping change taking place when
+	   the `r_brk' address is called.  */
+	RT_CONSISTENT,		/* Mapping change is complete.  */
+	RT_ADD,			/* Beginning to add a new object.  */
+	RT_DELETE		/* Beginning to remove an object mapping.  */
+      } r_state;
+
+    ElfW(Addr) r_ldbase;	/* Base address the linker is loaded at.  */
+  };
+
+/* This is the instance of that structure used by the dynamic linker.  */
+extern struct r_debug _r_debug;
+
+/* This symbol refers to the "dynamic structure" in the `.dynamic' section
+   of whatever module refers to `_DYNAMIC'.  So, to find its own
+   `struct r_debug', a program could do:
+     for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn)
+       if (dyn->d_tag == DT_DEBUG)
+	 r_debug = (struct r_debug *) dyn->d_un.d_ptr;
+   */
+extern ElfW(Dyn) _DYNAMIC[];
+
+/* Structure describing a loaded shared object.  The `l_next' and `l_prev'
+   members form a chain of all the shared objects loaded at startup.
+
+   These data structures exist in space used by the run-time dynamic linker;
+   modifying them may have disastrous results.  */
+
+struct link_map
+  {
+    /* These first few members are part of the protocol with the debugger.
+       This is the same format used in SVR4.  */
+
+    ElfW(Addr) l_addr;		/* Difference between the address in the ELF
+				   file and the addresses in memory.  */
+    char *l_name;		/* Absolute file name object was found in.  */
+    ElfW(Dyn) *l_ld;		/* Dynamic section of the shared object.  */
+    struct link_map *l_next, *l_prev; /* Chain of loaded objects.  */
+  };
+
+#ifdef __USE_GNU
+
+/* Version numbers for la_version handshake interface.  */
+#define LAV_CURRENT	1
+
+/* Activity types signaled through la_activity.  */
+enum
+  {
+    LA_ACT_CONSISTENT,		/* Link map consistent again.  */
+    LA_ACT_ADD,			/* New object will be added.  */
+    LA_ACT_DELETE		/* Objects will be removed.  */
+  };
+
+/* Values representing origin of name for dynamic loading.  */
+enum
+  {
+    LA_SER_ORIG = 0x01,		/* Original name.  */
+    LA_SER_LIBPATH = 0x02,	/* Directory from LD_LIBRARY_PATH.  */
+    LA_SER_RUNPATH = 0x04,	/* Directory from RPATH/RUNPATH.  */
+    LA_SER_CONFIG = 0x08,	/* Found through ldconfig.  */
+    LA_SER_DEFAULT = 0x40,	/* Default directory.  */
+    LA_SER_SECURE = 0x80	/* Unused.  */
+  };
+
+/* Values for la_objopen return value.  */
+enum
+  {
+    LA_FLG_BINDTO = 0x01,	/* Audit symbols bound to this object.  */
+    LA_FLG_BINDFROM = 0x02	/* Audit symbols bound from this object.  */
+  };
+
+/* Values for la_symbind flags parameter.  */
+enum
+  {
+    LA_SYMB_NOPLTENTER = 0x01,	/* la_pltenter will not be called.  */
+    LA_SYMB_NOPLTEXIT = 0x02,	/* la_pltexit will not be called.  */
+    LA_SYMB_STRUCTCALL = 0x04,	/* Return value is a structure.  */
+    LA_SYMB_DLSYM = 0x08,	/* Binding due to dlsym call.  */
+    LA_SYMB_ALTVALUE = 0x10	/* Value has been changed by a previous
+				   la_symbind call.  */
+  };
+
+struct dl_phdr_info
+  {
+    ElfW(Addr) dlpi_addr;
+    const char *dlpi_name;
+    const ElfW(Phdr) *dlpi_phdr;
+    ElfW(Half) dlpi_phnum;
+
+    /* Note: Following members were introduced after the first
+       version of this structure was available.  Check the SIZE
+       argument passed to the dl_iterate_phdr callback to determine
+       whether or not each later member is available.  */
+
+    /* Incremented when a new object may have been added.  */
+    __extension__ unsigned long long int dlpi_adds;
+    /* Incremented when an object may have been removed.  */
+    __extension__ unsigned long long int dlpi_subs;
+
+    /* If there is a PT_TLS segment, its module ID as used in
+       TLS relocations, else zero.  */
+    size_t dlpi_tls_modid;
+
+    /* The address of the calling thread's instance of this module's
+       PT_TLS segment, if it has one and it has been allocated
+       in the calling thread, otherwise a null pointer.  */
+    void *dlpi_tls_data;
+  };
+
+__BEGIN_DECLS
+
+extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *,
+					       size_t, void *),
+			    void *__data);
+
+
+/* Prototypes for the ld.so auditing interfaces.  These are not
+   defined anywhere in ld.so but instead have to be provided by the
+   auditing DSO.  */
+extern unsigned int la_version (unsigned int __version);
+extern void la_activity (uintptr_t *__cookie, unsigned int __flag);
+extern char *la_objsearch (const char *__name, uintptr_t *__cookie,
+			   unsigned int __flag);
+extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
+				uintptr_t *__cookie);
+extern void la_preinit (uintptr_t *__cookie);
+extern uintptr_t la_symbind32 (Elf32_Sym *__sym, unsigned int __ndx,
+			       uintptr_t *__refcook, uintptr_t *__defcook,
+			       unsigned int *__flags, const char *__symname);
+extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx,
+			       uintptr_t *__refcook, uintptr_t *__defcook,
+			       unsigned int *__flags, const char *__symname);
+extern unsigned int la_objclose (uintptr_t *__cookie);
+
+__END_DECLS
+
+#endif
+
+#endif /* link.h */
diff --git a/REORG.TODO/elf/loadfail.c b/REORG.TODO/elf/loadfail.c
new file mode 100644
index 0000000000..7531aa958e
--- /dev/null
+++ b/REORG.TODO/elf/loadfail.c
@@ -0,0 +1,42 @@
+#include <dlfcn.h>
+#include <error.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *su[5];
+  void *h;
+  int n;
+
+  mtrace ();
+
+  if ((su[0] = dlopen ("testobj1.so", RTLD_GLOBAL | RTLD_NOW)) == NULL
+      || (su[1] = dlopen ("testobj2.so", RTLD_GLOBAL | RTLD_NOW)) == NULL
+      || (su[2] = dlopen ("testobj3.so", RTLD_GLOBAL | RTLD_NOW)) == NULL
+      || (su[3] = dlopen ("testobj4.so", RTLD_GLOBAL | RTLD_NOW)) == NULL
+      || (su[4] = dlopen ("testobj5.so", RTLD_GLOBAL | RTLD_NOW)) == NULL)
+    error (EXIT_FAILURE, 0, "failed to load shared object: %s", dlerror ());
+
+  h = dlopen ("failobj.so", RTLD_GLOBAL | RTLD_NOW);
+
+  printf ("h = %p, %s\n", h, h == NULL ? "ok" : "fail");
+
+  for (n = 0; n < 5; ++n)
+    if (dlclose (su[n]) != 0)
+      {
+	printf ("failed to unload su[%d]: %s\n", n, dlerror ());
+	exit (EXIT_FAILURE);
+      }
+
+  return h != NULL;
+}
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return 10;
+}
diff --git a/REORG.TODO/elf/loadtest.c b/REORG.TODO/elf/loadtest.c
new file mode 100644
index 0000000000..727469b496
--- /dev/null
+++ b/REORG.TODO/elf/loadtest.c
@@ -0,0 +1,202 @@
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <error.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* How many load/unload operations do we do.  */
+#define TEST_ROUNDS	1000
+
+
+static struct
+{
+  /* Name of the module.  */
+  const char *name;
+  /* The handle.  */
+  void *handle;
+} testobjs[] =
+{
+  { "testobj1.so", NULL },
+  { "testobj2.so", NULL },
+  { "testobj3.so", NULL },
+  { "testobj4.so", NULL },
+  { "testobj5.so", NULL },
+  { "testobj6.so", NULL },
+};
+#define NOBJS	(sizeof (testobjs) / sizeof (testobjs[0]))
+
+
+static const struct
+{
+  /* Name of a function to call.  */
+  const char *fname;
+  /* Index in status and handle array.  */
+  int index;
+  /* Options while loading the module.  */
+  int options;
+} tests[] =
+{
+  { "obj1func2", 0, RTLD_LAZY },
+  { "obj1func1", 0, RTLD_LAZY | RTLD_GLOBAL },
+  { "obj1func1", 0, RTLD_NOW, },
+  { "obj1func2", 0, RTLD_NOW | RTLD_GLOBAL },
+  { "obj2func2", 1, RTLD_LAZY },
+  { "obj2func1", 1, RTLD_LAZY | RTLD_GLOBAL, },
+  { "obj2func1", 1, RTLD_NOW, },
+  { "obj2func2", 1, RTLD_NOW | RTLD_GLOBAL },
+  { "obj3func2", 2, RTLD_LAZY },
+  { "obj3func1", 2, RTLD_LAZY | RTLD_GLOBAL },
+  { "obj3func1", 2, RTLD_NOW },
+  { "obj3func2", 2, RTLD_NOW | RTLD_GLOBAL },
+  { "obj4func2", 3, RTLD_LAZY },
+  { "obj4func1", 3, RTLD_LAZY | RTLD_GLOBAL },
+  { "obj4func1", 3, RTLD_NOW },
+  { "obj4func2", 3, RTLD_NOW | RTLD_GLOBAL },
+  { "obj5func2", 4, RTLD_LAZY },
+  { "obj5func1", 4, RTLD_LAZY | RTLD_GLOBAL },
+  { "obj5func1", 4, RTLD_NOW },
+  { "obj5func2", 4, RTLD_NOW | RTLD_GLOBAL },
+  { "obj6func2", 5, RTLD_LAZY },
+  { "obj6func1", 5, RTLD_LAZY | RTLD_GLOBAL },
+  { "obj6func1", 5, RTLD_NOW },
+  { "obj6func2", 5, RTLD_NOW | RTLD_GLOBAL },
+};
+#define NTESTS	(sizeof (tests) / sizeof (tests[0]))
+
+
+#include <include/link.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+#define OUT \
+  for (map = MAPS; map != NULL; map = map->l_next)		      \
+    if (map->l_type == lt_loaded)					      \
+      printf ("name = \"%s\", direct_opencount = %d\n",			      \
+	      map->l_name, (int) map->l_direct_opencount);		      \
+  fflush (stdout)
+
+
+int
+main (int argc, char *argv[])
+{
+  int debug = argc > 1 && argv[1][0] != '\0';
+  int count = TEST_ROUNDS;
+  int result = 0;
+  struct link_map *map;
+
+  mtrace ();
+
+  /* Just a seed.  */
+  srandom (TEST_ROUNDS);
+
+  if (debug)
+    {
+      puts ("in the beginning");
+      OUT;
+    }
+
+  while (count--)
+    {
+      int nr = random () % NTESTS;
+      int index = tests[nr].index;
+
+      printf ("%4d: %4d: ", count + 1, nr);
+      fflush (stdout);
+
+      if (testobjs[index].handle == NULL)
+	{
+	  int (*fct) (int);
+
+	  /* Load the object.  */
+	  testobjs[index].handle = dlopen (testobjs[index].name,
+					   tests[nr].options);
+	  if (testobjs[index].handle == NULL)
+	    error (EXIT_FAILURE, 0, "cannot load `%s': %s",
+		   testobjs[index].name, dlerror ());
+
+	  /* Test the function call.  */
+	  fct = dlsym (testobjs[index].handle, tests[nr].fname);
+	  if (fct == NULL)
+	    error (EXIT_FAILURE, 0,
+		   "cannot get function `%s' from shared object `%s': %s",
+		   tests[nr].fname, testobjs[index].name, dlerror ());
+
+	  fct (10);
+
+	  printf ("successfully loaded `%s', handle %p\n",
+		  testobjs[index].name, testobjs[index].handle);
+	}
+      else
+	{
+	  if (dlclose (testobjs[index].handle) != 0)
+	    {
+	      printf ("failed to close %s\n", testobjs[index].name);
+	      result = 1;
+	    }
+	  else
+	    printf ("successfully unloaded `%s', handle %p\n",
+		    testobjs[index].name, testobjs[index].handle);
+
+	  testobjs[index].handle = NULL;
+
+	  if (testobjs[0].handle == NULL
+	      && testobjs[1].handle == NULL
+	      && testobjs[5].handle == NULL)
+	    {
+	      /* In this case none of the objects above should be
+		 present.  */
+	      for (map = MAPS; map != NULL; map = map->l_next)
+		if (map->l_type == lt_loaded
+		    && (strstr (map->l_name, testobjs[0].name) != NULL
+			|| strstr (map->l_name, testobjs[1].name) != NULL
+			|| strstr (map->l_name, testobjs[5].name) != NULL))
+		  {
+		    printf ("`%s' is still loaded\n", map->l_name);
+		    result = 1;
+		  }
+	    }
+	}
+
+      if (debug)
+	OUT;
+    }
+
+  /* Unload all loaded modules.  */
+  for (count = 0; count < (int) NOBJS; ++count)
+    if (testobjs[count].handle != NULL)
+      {
+	printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
+		testobjs[count].name,
+		((struct link_map *) testobjs[count].handle)->l_initfini,
+		((struct link_map *) testobjs[count].handle)->l_versions);
+
+	if (dlclose (testobjs[count].handle) != 0)
+	  {
+	    printf ("failed to close %s\n", testobjs[count].name);
+	    result = 1;
+	  }
+      }
+
+  /* Check whether all files are unloaded.  */
+  for (map = MAPS; map != NULL; map = map->l_next)
+    if (map->l_type == lt_loaded)
+      {
+	printf ("name = \"%s\", direct_opencount = %d\n",
+		map->l_name, (int) map->l_direct_opencount);
+	result = 1;
+      }
+
+  return result;
+}
+
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return a - 1;
+}
diff --git a/REORG.TODO/elf/ltglobmod1.c b/REORG.TODO/elf/ltglobmod1.c
new file mode 100644
index 0000000000..300fa9a89f
--- /dev/null
+++ b/REORG.TODO/elf/ltglobmod1.c
@@ -0,0 +1,7 @@
+extern int bar (void);
+
+int
+bar (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/ltglobmod2.c b/REORG.TODO/elf/ltglobmod2.c
new file mode 100644
index 0000000000..33f14cc980
--- /dev/null
+++ b/REORG.TODO/elf/ltglobmod2.c
@@ -0,0 +1,33 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int bar (void);
+extern int foo (void);
+
+int
+foo (void)
+{
+  void *h;
+  int res;
+
+  /* Load ltglobalmod1 in the global namespace.  */
+  h = dlopen ("ltglobmod1.so", RTLD_GLOBAL | RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("%s: cannot open %s: %s",
+	      __FUNCTION__, "ltglobmod1.so", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  /* Call bar.  This is undefined in the DSO.  */
+  puts ("about to call `bar'");
+  fflush (stdout);
+  res = bar ();
+
+  printf ("bar returned %d\n", res);
+
+  dlclose (h);
+
+  return res != 42;
+}
diff --git a/REORG.TODO/elf/multiload.c b/REORG.TODO/elf/multiload.c
new file mode 100644
index 0000000000..e85cc96589
--- /dev/null
+++ b/REORG.TODO/elf/multiload.c
@@ -0,0 +1,105 @@
+#include <dlfcn.h>
+#include <errno.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main (void)
+{
+  void *a;
+  void *b;
+  void *c;
+  void *d;
+  char *wd;
+  char *base;
+  char *buf;
+
+  mtrace ();
+
+  /* Change to the binary directory.  */
+  if (chdir (OBJDIR) != 0)
+    {
+      printf ("cannot change to `%s': %m", OBJDIR);
+      exit (EXIT_FAILURE);
+    }
+
+  wd = getcwd (NULL, 0);
+  base = basename (wd);
+  buf = alloca (strlen (wd) + strlen (base) + 5 + sizeof "testobj1.so");
+
+  printf ("loading `%s'\n", "./testobj1.so");
+  a = dlopen ("./testobj1.so", RTLD_NOW);
+  if (a == NULL)
+    {
+      printf ("cannot load `./testobj1.so': %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (stpcpy (buf, "../"), base), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  b = dlopen (buf, RTLD_NOW);
+  if (b == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (buf, wd), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  c = dlopen (buf, RTLD_NOW);
+  if (c == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (stpcpy (stpcpy (buf, wd), "/../"), base), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  d = dlopen (buf, RTLD_NOW);
+  if (d == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  if (a != b || b != c || c != d)
+    {
+      puts ("shared object loaded more than once");
+      exit (EXIT_FAILURE);
+    }
+
+  if (dlclose (a) != 0)
+    {
+      puts ("closing `a' failed");
+      exit (EXIT_FAILURE);
+    }
+  if (dlclose (b) != 0)
+    {
+      puts ("closing `a' failed");
+      exit (EXIT_FAILURE);
+    }
+  if (dlclose (c) != 0)
+    {
+      puts ("closing `a' failed");
+      exit (EXIT_FAILURE);
+    }
+  if (dlclose (d) != 0)
+    {
+      puts ("closing `a' failed");
+      exit (EXIT_FAILURE);
+    }
+
+  free (wd);
+
+  return 0;
+}
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return a;
+}
diff --git a/REORG.TODO/elf/neededobj1.c b/REORG.TODO/elf/neededobj1.c
new file mode 100644
index 0000000000..eb55adab39
--- /dev/null
+++ b/REORG.TODO/elf/neededobj1.c
@@ -0,0 +1,6 @@
+extern void c_function (void);
+
+void
+c_function (void)
+{
+}
diff --git a/REORG.TODO/elf/neededobj2.c b/REORG.TODO/elf/neededobj2.c
new file mode 100644
index 0000000000..5ad8a51d62
--- /dev/null
+++ b/REORG.TODO/elf/neededobj2.c
@@ -0,0 +1,8 @@
+extern void b_function (void);
+extern void c_function (void);
+
+void
+b_function (void)
+{
+  c_function();
+}
diff --git a/REORG.TODO/elf/neededobj3.c b/REORG.TODO/elf/neededobj3.c
new file mode 100644
index 0000000000..da25329aa7
--- /dev/null
+++ b/REORG.TODO/elf/neededobj3.c
@@ -0,0 +1,10 @@
+extern void a_function (void);
+extern void b_function (void);
+extern void c_function (void);
+
+void
+a_function (void)
+{
+  b_function ();
+  c_function ();
+}
diff --git a/REORG.TODO/elf/neededobj4.c b/REORG.TODO/elf/neededobj4.c
new file mode 100644
index 0000000000..3ea8540047
--- /dev/null
+++ b/REORG.TODO/elf/neededobj4.c
@@ -0,0 +1,12 @@
+extern void a_function (void);
+extern void b_function (void);
+extern void c_function (void);
+extern void d_function (void);
+
+void
+d_function (void)
+{
+  a_function ();
+  b_function ();
+  c_function ();
+}
diff --git a/REORG.TODO/elf/neededobj5.c b/REORG.TODO/elf/neededobj5.c
new file mode 100644
index 0000000000..2d629b0880
--- /dev/null
+++ b/REORG.TODO/elf/neededobj5.c
@@ -0,0 +1,5 @@
+extern void a1_function (void);
+
+void a1_function (void)
+{
+}
diff --git a/REORG.TODO/elf/neededobj6.c b/REORG.TODO/elf/neededobj6.c
new file mode 100644
index 0000000000..639b6f195e
--- /dev/null
+++ b/REORG.TODO/elf/neededobj6.c
@@ -0,0 +1,7 @@
+extern void a1_function (void);
+extern void a2_function (void);
+
+void a2_function (void)
+{
+  a1_function ();
+}
diff --git a/REORG.TODO/elf/neededtest.c b/REORG.TODO/elf/neededtest.c
new file mode 100644
index 0000000000..3cea499314
--- /dev/null
+++ b/REORG.TODO/elf/neededtest.c
@@ -0,0 +1,125 @@
+#include <dlfcn.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+static int
+check_loaded_objects (const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int errors = 0;
+
+  for (n = 0; loaded[n]; n++)
+    /* NOTHING */;
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = MAPS; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name[0])
+	printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded[n] != NULL; n++)
+	    {
+	      if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0)
+	        {
+		  found[n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (match == 0)
+	    {
+	      ++errors;
+	      printf ("ERRORS: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded[n] != NULL; n++)
+    {
+      if (found[n] == 0)
+        {
+	  ++errors;
+	  printf ("ERRORS: %s is not loaded\n", loaded[n]);
+	}
+    }
+
+  return errors;
+}
+
+int
+main (void)
+{
+  void *obj2[2];
+  void *obj3;
+  const char *loaded[] = { NULL, NULL, NULL, NULL };
+  int errors = 0;
+
+  printf ("\nThis is what is in memory now:\n");
+  errors += check_loaded_objects (loaded);
+
+  printf( "Loading shared object neededobj3.so\n");
+  obj3 = dlopen( "neededobj3.so", RTLD_LAZY);
+  if (obj3 == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[0] = "neededobj1.so";
+  loaded[1] = "neededobj2.so";
+  loaded[2] = "neededobj3.so";
+  errors += check_loaded_objects (loaded);
+
+  printf ("Now loading shared object neededobj2.so\n");
+  obj2[0] = dlopen ("neededobj2.so", RTLD_LAZY);
+  if (obj2[0] == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  errors += check_loaded_objects (loaded);
+
+  printf ("And loading shared object neededobj2.so again\n");
+  obj2[1] = dlopen ("neededobj2.so", RTLD_LAZY);
+  if (obj2[1] == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj2.so for the first time\n");
+  dlclose (obj2[0]);
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj3.so\n");
+  dlclose (obj3);
+  loaded[2] = NULL;
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj2.so for the second time\n");
+  dlclose (obj2[1]);
+  loaded[0] = NULL;
+  loaded[1] = NULL;
+  errors += check_loaded_objects (loaded);
+
+  if (errors != 0)
+    printf ("%d errors found\n", errors);
+  return errors;
+}
diff --git a/REORG.TODO/elf/neededtest2.c b/REORG.TODO/elf/neededtest2.c
new file mode 100644
index 0000000000..17c75f2ba3
--- /dev/null
+++ b/REORG.TODO/elf/neededtest2.c
@@ -0,0 +1,118 @@
+#include <dlfcn.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+static int
+check_loaded_objects (const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int errors = 0;
+
+  for (n = 0; loaded[n]; n++)
+    /* NOTHING */;
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = MAPS; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name[0])
+	printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded[n] != NULL; n++)
+	    {
+	      if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0)
+	        {
+		  found[n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (match == 0)
+	    {
+	      ++errors;
+	      printf ("ERRORS: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded[n] != NULL; n++)
+    {
+      if (found[n] == 0)
+        {
+	  ++errors;
+	  printf ("ERRORS: %s is not loaded\n", loaded[n]);
+	}
+    }
+
+  return errors;
+}
+
+int
+main (void)
+{
+  void *obj2;
+  void *obj3[2];
+  const char *loaded[] = { NULL, NULL, NULL, NULL };
+  int errors = 0;
+
+  printf ("\nThis is what is in memory now:\n");
+  errors += check_loaded_objects (loaded);
+  printf ("\nLoading shared object neededobj2.so\n");
+  obj2 = dlopen ("neededobj2.so", RTLD_LAZY);
+  if (obj2 == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[0] = "neededobj1.so";
+  loaded[1] = "neededobj2.so";
+  errors += check_loaded_objects (loaded);
+  printf ("\nLoading shared object neededobj3.so\n");
+  obj3[0] = dlopen( "neededobj3.so", RTLD_LAZY);
+  if (obj3[0] == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[2] = "neededobj3.so";
+  errors += check_loaded_objects (loaded);
+  printf ("\nNow loading shared object neededobj3.so again\n");
+  obj3[1] = dlopen ("neededobj3.so", RTLD_LAZY);
+  if (obj3[1] == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  errors += check_loaded_objects (loaded);
+  printf ("\nClosing neededobj3.so once\n");
+  dlclose (obj3[0]);
+  errors += check_loaded_objects (loaded);
+  printf ("\nClosing neededobj2.so\n");
+  dlclose (obj2);
+  errors += check_loaded_objects (loaded);
+  printf ("\nClosing neededobj3.so for the second time\n");
+  dlclose (obj3[1]);
+  loaded[0] = NULL;
+  loaded[1] = NULL;
+  loaded[2] = NULL;
+  errors += check_loaded_objects (loaded);
+  if (errors != 0)
+    printf ("%d errors found\n", errors);
+  return errors;
+}
diff --git a/REORG.TODO/elf/neededtest3.c b/REORG.TODO/elf/neededtest3.c
new file mode 100644
index 0000000000..41970cf2c7
--- /dev/null
+++ b/REORG.TODO/elf/neededtest3.c
@@ -0,0 +1,129 @@
+#include <dlfcn.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+static int
+check_loaded_objects (const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int errors = 0;
+
+  for (n = 0; loaded[n]; n++)
+    /* NOTHING */;
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = MAPS; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name[0])
+	printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded[n] != NULL; n++)
+	    {
+	      if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0)
+	        {
+		  found[n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (match == 0)
+	    {
+	      ++errors;
+	      printf ("ERRORS: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded[n] != NULL; n++)
+    {
+      if (found[n] == 0)
+        {
+	  ++errors;
+	  printf ("ERRORS: %s is not loaded\n", loaded[n]);
+	}
+    }
+
+  return errors;
+}
+
+int
+main (void)
+{
+  void *obj2;
+  void *obj3;
+  void *obj4;
+  const char *loaded[] = { NULL, NULL, NULL, NULL, NULL };
+  int errors = 0;
+
+  printf ("\nThis is what is in memory now:\n");
+  errors += check_loaded_objects (loaded);
+
+  printf ("Now loading shared object neededobj2.so\n");
+  obj2 = dlopen ("neededobj2.so", RTLD_LAZY);
+  if (obj2 == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[0] = "neededobj1.so";
+  loaded[1] = "neededobj2.so";
+  errors += check_loaded_objects (loaded);
+
+  printf( "Loading shared object neededobj3.so\n");
+  obj3 = dlopen( "neededobj3.so", RTLD_LAZY);
+  if (obj3 == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[2] = "neededobj3.so";
+  errors += check_loaded_objects (loaded);
+
+
+  printf( "Loading shared object neededobj4.so\n");
+  obj4 = dlopen( "neededobj4.so", RTLD_LAZY);
+  if (obj4 == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  loaded[3] = "neededobj4.so";
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj2.so\n");
+  dlclose (obj2);
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj3.so\n");
+  dlclose (obj3);
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj4.so\n");
+  dlclose (obj4);
+  loaded[0] = NULL;
+  loaded[1] = NULL;
+  loaded[2] = NULL;
+  loaded[3] = NULL;
+  errors += check_loaded_objects (loaded);
+
+  if (errors != 0)
+    printf ("%d errors found\n", errors);
+  return errors;
+}
diff --git a/REORG.TODO/elf/neededtest4.c b/REORG.TODO/elf/neededtest4.c
new file mode 100644
index 0000000000..0ae0b7ff47
--- /dev/null
+++ b/REORG.TODO/elf/neededtest4.c
@@ -0,0 +1,158 @@
+#include <dlfcn.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+static int
+check_loaded_objects (const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int errors = 0;
+
+  for (n = 0; loaded[n]; n++)
+    /* NOTHING */;
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = MAPS; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name[0])
+	printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded[n] != NULL; n++)
+	    {
+	      if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0)
+		{
+		  found[n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (match == 0)
+	    {
+	      ++errors;
+	      printf ("ERRORS: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded[n] != NULL; n++)
+    {
+      if (found[n] == 0)
+	{
+	  ++errors;
+	  printf ("ERRORS: %s is not loaded\n", loaded[n]);
+	}
+    }
+
+  return errors;
+}
+
+extern void c_function (void);
+extern char *dirname (const char *__filename);
+
+int
+main (int argc, char **argv)
+{
+  void *obj;
+  const char *loaded[] = { NULL, NULL, NULL};
+  int errors = 0;
+  void (*f) (void);
+  const char *dir = dirname (argv [0]);
+  char *oldfilename;
+  char *newfilename;
+
+  c_function ();
+
+  printf ("\nThis is what is in memory now:\n");
+  errors += check_loaded_objects (loaded);
+
+  printf( "Loading shared object neededobj6.so\n");
+  obj = dlopen( "neededobj6.so", RTLD_LAZY);
+  if (obj == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  f = dlsym (obj, "a2_function");
+  if (f == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  f ();
+  loaded[0] = "neededobj5.so";
+  loaded[1] = "neededobj6.so";
+  errors += check_loaded_objects (loaded);
+
+  printf ("Closing neededobj6.so\n");
+  dlclose (obj);
+  loaded[0] = NULL;
+  errors += check_loaded_objects (loaded);
+
+  printf ("Rename neededobj5.so\n");
+  oldfilename = alloca (strlen (dir) + 1 + sizeof ("neededobj5.so"));
+  strcpy (oldfilename, dir);
+  strcat (oldfilename, "/");
+  strcat (oldfilename, "neededobj5.so");
+  newfilename = alloca (strlen (oldfilename) + sizeof (".renamed"));
+  strcpy (newfilename, oldfilename);
+  strcat (newfilename, ".renamed");
+  if (rename (oldfilename, newfilename))
+    {
+      perror ("rename");
+      exit (1);
+    }
+
+  printf( "Loading shared object neededobj6.so\n");
+  obj = dlopen( "neededobj6.so", RTLD_LAZY);
+  if (obj == NULL)
+    printf ("%s\n", dlerror ());
+  else
+    {
+      printf ("neededobj6.so should fail to load\n");
+      exit (1);
+    }
+
+  printf( "Loading shared object neededobj1.so\n");
+  obj = dlopen( "neededobj1.so", RTLD_LAZY);
+  if (obj == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  errors += check_loaded_objects (loaded);
+  f = dlsym (obj, "c_function");
+  if (f == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  f ();
+
+  printf ("Restore neededobj5.so\n");
+  if (rename (newfilename, oldfilename))
+    {
+      perror ("rename");
+      exit (1);
+    }
+
+  if (errors != 0)
+    printf ("%d errors found\n", errors);
+  return errors;
+}
diff --git a/REORG.TODO/elf/next.c b/REORG.TODO/elf/next.c
new file mode 100644
index 0000000000..a0d532b8c3
--- /dev/null
+++ b/REORG.TODO/elf/next.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+
+extern int successful_rtld_next_test (void);
+extern void *failing_rtld_next_use (void);
+
+
+static int
+do_test (void)
+{
+  int result;
+  void *addr;
+
+  /* First try call a function which uses RTLD_NEXT and calls that
+     function.  */
+  result = successful_rtld_next_test ();
+  if (result == 42)
+    {
+      puts ("RTLD_NEXT seems to work for existing functions");
+      result = 0;
+    }
+  else
+    {
+      printf ("Heh?  `successful_rtld_next_test' returned %d\n", result);
+      result = 1;
+    }
+
+  /* Next try a function which tries to get a function with RTLD_NEXT
+     but that fails.  This dlsym() call should return a NULL pointer
+     and do nothing else.  */
+  addr = failing_rtld_next_use ();
+  if (addr == NULL)
+    puts ("dlsym returned NULL for non-existing function.  Good");
+  else
+    {
+      puts ("dlsym found something !?");
+      result = 1;
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/nextmod1.c b/REORG.TODO/elf/nextmod1.c
new file mode 100644
index 0000000000..56de3536a0
--- /dev/null
+++ b/REORG.TODO/elf/nextmod1.c
@@ -0,0 +1,30 @@
+#include <dlfcn.h>
+
+extern int successful_rtld_next_test (void);
+extern void *failing_rtld_next_use (void);
+
+int nextmod1_dummy_var;
+
+int
+successful_rtld_next_test (void)
+{
+  int (*fp) (void);
+
+  /* Get the next function... */
+  fp = (int (*) (void)) dlsym (RTLD_NEXT, __FUNCTION__);
+
+  /* ...and simply call it.  */
+  return fp ();
+}
+
+
+void *
+failing_rtld_next_use (void)
+{
+  void *ret = dlsym (RTLD_NEXT, __FUNCTION__);
+
+  /* Ensure we are not tail call optimized, because then RTLD_NEXT
+     might return this function.  */
+  ++nextmod1_dummy_var;
+  return ret;
+}
diff --git a/REORG.TODO/elf/nextmod2.c b/REORG.TODO/elf/nextmod2.c
new file mode 100644
index 0000000000..b2c435f341
--- /dev/null
+++ b/REORG.TODO/elf/nextmod2.c
@@ -0,0 +1,10 @@
+/* Very elaborated function.  */
+
+extern int successful_rtld_next_test (void);
+
+
+int
+successful_rtld_next_test (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/nodel2mod1.c b/REORG.TODO/elf/nodel2mod1.c
new file mode 100644
index 0000000000..acddc4cf8b
--- /dev/null
+++ b/REORG.TODO/elf/nodel2mod1.c
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+void
+foo (void)
+{
+  exit (0);
+}
+
+void
+__attribute__((destructor))
+bar (void)
+{
+  static int i;
+  foo ();
+  ++i;
+}
+void
+baz (void)
+{
+}
diff --git a/REORG.TODO/elf/nodel2mod2.c b/REORG.TODO/elf/nodel2mod2.c
new file mode 100644
index 0000000000..d0020240a8
--- /dev/null
+++ b/REORG.TODO/elf/nodel2mod2.c
@@ -0,0 +1,7 @@
+void
+__attribute__((constructor))
+xxx (void)
+{
+  extern void baz (void);
+  baz ();
+}
diff --git a/REORG.TODO/elf/nodel2mod3.c b/REORG.TODO/elf/nodel2mod3.c
new file mode 100644
index 0000000000..6d1a0d47b7
--- /dev/null
+++ b/REORG.TODO/elf/nodel2mod3.c
@@ -0,0 +1 @@
+int x;
diff --git a/REORG.TODO/elf/nodelete.c b/REORG.TODO/elf/nodelete.c
new file mode 100644
index 0000000000..c8d71152f2
--- /dev/null
+++ b/REORG.TODO/elf/nodelete.c
@@ -0,0 +1,210 @@
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+
+
+static sigjmp_buf jmpbuf;
+
+
+int fini_ran;
+
+
+static void
+__attribute__ ((noreturn))
+handler (int sig)
+{
+  siglongjmp (jmpbuf, 1);
+}
+
+
+static int
+do_test (void)
+{
+  /* We are testing the two possibilities to mark an object as not deletable:
+     - marked on the linker commandline with `-z nodelete'
+     - with the RTLD_NODELETE flag at dlopen()-time.
+
+     The test we are performing should be safe.  We are loading the objects,
+     get the address of variables in the respective object, unload the object
+     and then try to read the variable.  If the object is unloaded this
+     should lead to an segmentation fault.  */
+  int result = 0;
+  void *p;
+  struct sigaction sa;
+
+  sa.sa_handler = handler;
+  sigfillset (&sa.sa_mask);
+  sa.sa_flags = SA_RESTART;
+
+  if (sigaction (SIGSEGV, &sa, NULL) == -1)
+    printf ("cannot install signal handler: %m\n");
+
+  p = dlopen ("nodelmod1.so", RTLD_LAZY);
+  if (p == NULL)
+    {
+      printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    {
+      int *varp;
+
+      puts ("succeeded loading \"nodelmod1.so\"");
+
+      varp = dlsym (p, "var1");
+      if (varp == NULL)
+	{
+	  puts ("failed to get address of \"var1\" in \"nodelmod1.so\"");
+	  result = 1;
+	}
+      else
+	{
+	  *varp = 20000720;
+
+	  /* Now close the object.  */
+	  fini_ran = 0;
+	  if (dlclose (p) != 0)
+	    {
+	      puts ("failed to close \"nodelmod1.so\"");
+	      result = 1;
+	    }
+	  else if (! sigsetjmp (jmpbuf, 1))
+	    {
+	      /* Access the variable again.  */
+	      if (*varp != 20000720)
+		{
+		  puts ("\"var1\" value not correct");
+		  result = 1;
+		}
+	      else if (fini_ran != 0)
+		{
+		  puts ("destructor of \"nodelmod1.so\" ran");
+		  result = 1;
+		}
+	      else
+		puts ("-z nodelete test succeeded");
+	    }
+	  else
+	    {
+	      /* We caught an segmentation fault.  */
+	      puts ("\"nodelmod1.so\" got deleted");
+	      result = 1;
+	    }
+	}
+    }
+
+  p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE);
+  if (p == NULL)
+    {
+      printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    {
+      int *varp;
+
+      puts ("succeeded loading \"nodelmod2.so\"");
+
+      varp = dlsym (p, "var2");
+      if (varp == NULL)
+	{
+	  puts ("failed to get address of \"var2\" in \"nodelmod2.so\"");
+	  result = 1;
+	}
+      else
+	{
+	  *varp = 42;
+
+	  /* Now close the object.  */
+	  fini_ran = 0;
+	  if (dlclose (p) != 0)
+	    {
+	      puts ("failed to close \"nodelmod2.so\"");
+	      result = 1;
+	    }
+	  else if (! sigsetjmp (jmpbuf, 1))
+	    {
+	      /* Access the variable again.  */
+	      if (*varp != 42)
+		{
+		  puts ("\"var2\" value not correct");
+		  result = 1;
+		}
+	      else if (fini_ran != 0)
+		{
+		  puts ("destructor of \"nodelmod2.so\" ran");
+		  result = 1;
+		}
+	      else
+		puts ("RTLD_NODELETE test succeeded");
+	    }
+	  else
+	    {
+	      /* We caught an segmentation fault.  */
+	      puts ("\"nodelmod2.so\" got deleted");
+	      result = 1;
+	    }
+	}
+    }
+
+  p = dlopen ("nodelmod3.so", RTLD_LAZY);
+  if (p == NULL)
+    {
+      printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    {
+      int *(*fctp) (void);
+
+      puts ("succeeded loading \"nodelmod3.so\"");
+
+      fctp = dlsym (p, "addr");
+      if (fctp == NULL)
+	{
+	  puts ("failed to get address of \"addr\" in \"nodelmod3.so\"");
+	  result = 1;
+	}
+      else
+	{
+	  int *varp = fctp ();
+
+	  *varp = -1;
+
+	  /* Now close the object.  */
+	  fini_ran = 0;
+	  if (dlclose (p) != 0)
+	    {
+	      puts ("failed to close \"nodelmod3.so\"");
+	      result = 1;
+	    }
+	  else if (! sigsetjmp (jmpbuf, 1))
+	    {
+	      /* Access the variable again.  */
+	      if (*varp != -1)
+		{
+		  puts ("\"var_in_mod4\" value not correct");
+		  result = 1;
+		}
+	      else if (fini_ran != 0)
+		{
+		  puts ("destructor of \"nodelmod4.so\" ran");
+		  result = 1;
+		}
+	      else
+		puts ("-z nodelete in dependency succeeded");
+	    }
+	  else
+	    {
+	      /* We caught an segmentation fault.  */
+	      puts ("\"nodelmod4.so\" got deleted");
+	      result = 1;
+	    }
+	}
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/nodelete2.c b/REORG.TODO/elf/nodelete2.c
new file mode 100644
index 0000000000..b3d7e31a08
--- /dev/null
+++ b/REORG.TODO/elf/nodelete2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+int
+main (void)
+{
+  void *handle = dlopen ("nodel2mod3.so", RTLD_LAZY);
+  if (handle == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  dlclose (handle);
+  exit (1);
+}
diff --git a/REORG.TODO/elf/nodelmod1.c b/REORG.TODO/elf/nodelmod1.c
new file mode 100644
index 0000000000..fc24a7b172
--- /dev/null
+++ b/REORG.TODO/elf/nodelmod1.c
@@ -0,0 +1,9 @@
+int var1 = 42;
+
+static void
+__attribute__ ((__destructor__))
+destr (void)
+{
+  extern int fini_ran;
+  fini_ran = 1;
+}
diff --git a/REORG.TODO/elf/nodelmod2.c b/REORG.TODO/elf/nodelmod2.c
new file mode 100644
index 0000000000..6bd7108a13
--- /dev/null
+++ b/REORG.TODO/elf/nodelmod2.c
@@ -0,0 +1,9 @@
+int var2 = 100;
+
+static void
+__attribute__ ((__destructor__))
+destr (void)
+{
+  extern int fini_ran;
+  fini_ran = 1;
+}
diff --git a/REORG.TODO/elf/nodelmod3.c b/REORG.TODO/elf/nodelmod3.c
new file mode 100644
index 0000000000..817c94db6e
--- /dev/null
+++ b/REORG.TODO/elf/nodelmod3.c
@@ -0,0 +1,8 @@
+extern int var_in_mod4;
+extern int *addr (void);
+
+int *
+addr (void)
+{
+  return &var_in_mod4;
+}
diff --git a/REORG.TODO/elf/nodelmod4.c b/REORG.TODO/elf/nodelmod4.c
new file mode 100644
index 0000000000..2cca43a6e8
--- /dev/null
+++ b/REORG.TODO/elf/nodelmod4.c
@@ -0,0 +1,9 @@
+int var_in_mod4 = 99;
+
+static void
+__attribute__ ((__destructor__))
+destr (void)
+{
+  extern int fini_ran;
+  fini_ran = 1;
+}
diff --git a/REORG.TODO/elf/nodlopen.c b/REORG.TODO/elf/nodlopen.c
new file mode 100644
index 0000000000..642bdb3011
--- /dev/null
+++ b/REORG.TODO/elf/nodlopen.c
@@ -0,0 +1,15 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  if (dlopen ("nodlopenmod.so", RTLD_LAZY) != NULL)
+    {
+      puts ("opening \"nodlopenmod.so\" succeeded, FAIL");
+      return 1;
+    }
+
+  puts ("opening \"nodlopenmod.so\" failed, OK");
+  return 0;
+}
diff --git a/REORG.TODO/elf/nodlopen2.c b/REORG.TODO/elf/nodlopen2.c
new file mode 100644
index 0000000000..a223f36834
--- /dev/null
+++ b/REORG.TODO/elf/nodlopen2.c
@@ -0,0 +1,15 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  if (dlopen ("nodlopenmod2.so", RTLD_LAZY) != NULL)
+    {
+      puts ("opening \"nodlopenmod2.so\" succeeded, FAIL");
+      return 1;
+    }
+
+  puts ("opening \"nodlopenmod2.so\" failed, OK");
+  return 0;
+}
diff --git a/REORG.TODO/elf/nodlopenmod.c b/REORG.TODO/elf/nodlopenmod.c
new file mode 100644
index 0000000000..4bcf8c9786
--- /dev/null
+++ b/REORG.TODO/elf/nodlopenmod.c
@@ -0,0 +1 @@
+int a = 42;
diff --git a/REORG.TODO/elf/nodlopenmod2.c b/REORG.TODO/elf/nodlopenmod2.c
new file mode 100644
index 0000000000..e72ae53e95
--- /dev/null
+++ b/REORG.TODO/elf/nodlopenmod2.c
@@ -0,0 +1,9 @@
+extern int a;
+
+extern int foo (void);
+
+int
+foo (void)
+{
+  return a;
+}
diff --git a/REORG.TODO/elf/noload.c b/REORG.TODO/elf/noload.c
new file mode 100644
index 0000000000..bcc85efc27
--- /dev/null
+++ b/REORG.TODO/elf/noload.c
@@ -0,0 +1,81 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <mcheck.h>
+
+int
+main (void)
+{
+  int result = 0;
+  void *p;
+
+  mtrace ();
+
+  /* First try to load an object which is a dependency.  This should
+     succeed.  */
+  p = dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD);
+  if (p == NULL)
+    {
+      printf ("cannot open \"testobj1.so\": %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    {
+      puts ("loading \"testobj1.so\" succeeded, OK");
+      dlclose (p);
+    }
+
+  /* Now try loading an object which is not already loaded.  */
+  if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+    {
+      puts ("succeeded in loading \"testobj5.so\"");
+      result = 1;
+    }
+  else
+    {
+      /* Load the object and run the same test again.  */
+      puts ("\"testobj5.so\" wasn't loaded and RTLD_NOLOAD prevented it, OK");
+
+      p = dlopen ("testobj5.so", RTLD_LAZY);
+
+      if (p == NULL)
+	{
+	  printf ("cannot open \"testobj5.so\" without RTLD_NOLOAD: %s\n",
+		  dlerror ());
+	  result = 1;
+	}
+      else
+	{
+	  puts ("loading \"testobj5.so\" succeeded, OK");
+
+	  void *q = dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD);
+	  if (q == NULL)
+	    {
+	      printf ("cannot open \"testobj5.so\": %s\n", dlerror ());
+	      result = 1;
+	    }
+	  else
+	    {
+	      puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK");
+	      dlclose (q);
+	    }
+
+	  if (dlclose (p) != 0)
+	    {
+	      printf ("cannot close \"testobj5.so\": %s\n", dlerror ());
+	      result = 1;
+	    }
+	  else
+	    puts ("closing \"testobj5.so\" succeeded, OK");
+	}
+    }
+
+  return result;
+}
+
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return 42 + a;
+}
diff --git a/REORG.TODO/elf/order.c b/REORG.TODO/elf/order.c
new file mode 100644
index 0000000000..ca617cbc09
--- /dev/null
+++ b/REORG.TODO/elf/order.c
@@ -0,0 +1,25 @@
+#include <unistd.h>
+
+void init (void) __attribute__ ((constructor));
+void
+__attribute__ ((constructor))
+init (void)
+{
+  write (1, "4", 1);
+}
+
+void fini (void) __attribute__ ((destructor));
+void
+__attribute__ ((destructor))
+fini (void)
+{
+  write (1, "5", 1);
+}
+
+extern int dep1 (void);
+
+int
+main (void)
+{
+  return dep1 () != 42;
+}
diff --git a/REORG.TODO/elf/order2.c b/REORG.TODO/elf/order2.c
new file mode 100644
index 0000000000..bcf266d5b1
--- /dev/null
+++ b/REORG.TODO/elf/order2.c
@@ -0,0 +1,45 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+int call_puts;
+
+static int
+do_test (void)
+{
+  call_puts = 1;
+
+  void *h1 = dlopen ("$ORIGIN/order2mod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      puts ("cannot load order2mod1");
+      return 1;
+    }
+  void *h2 = dlopen ("$ORIGIN/order2mod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("cannot load order2mod2");
+      return 1;
+    }
+  if (dlclose (h1) != 0)
+    {
+      puts ("dlclose order2mod1 failed");
+      return 1;
+    }
+  if (dlclose (h2) != 0)
+    {
+      puts ("dlclose order2mod2 failed");
+      return 1;
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  if (call_puts)
+    puts ("5");
+}
diff --git a/REORG.TODO/elf/order2mod1.c b/REORG.TODO/elf/order2mod1.c
new file mode 100644
index 0000000000..b695db29b7
--- /dev/null
+++ b/REORG.TODO/elf/order2mod1.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  putchar ('1');
+}
diff --git a/REORG.TODO/elf/order2mod2.c b/REORG.TODO/elf/order2mod2.c
new file mode 100644
index 0000000000..026cd2acc4
--- /dev/null
+++ b/REORG.TODO/elf/order2mod2.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+extern int foo (void);
+extern int bar (void);
+
+void
+__attribute__ ((constructor))
+init (void)
+{
+  (void) (foo () - bar ());
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  putchar ('2');
+}
diff --git a/REORG.TODO/elf/order2mod3.c b/REORG.TODO/elf/order2mod3.c
new file mode 100644
index 0000000000..7913a79925
--- /dev/null
+++ b/REORG.TODO/elf/order2mod3.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int
+bar (void)
+{
+  return 1;
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  putchar ('4');
+}
diff --git a/REORG.TODO/elf/order2mod4.c b/REORG.TODO/elf/order2mod4.c
new file mode 100644
index 0000000000..4f2026f041
--- /dev/null
+++ b/REORG.TODO/elf/order2mod4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return 42 + bar ();
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+  putchar ('3');
+}
diff --git a/REORG.TODO/elf/origtest.c b/REORG.TODO/elf/origtest.c
new file mode 100644
index 0000000000..1cacabcc39
--- /dev/null
+++ b/REORG.TODO/elf/origtest.c
@@ -0,0 +1,39 @@
+#include <dlfcn.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h;
+  int (*fp) (int);
+  int res;
+
+  h = dlopen ("${ORIGIN}/testobj1.so", RTLD_LAZY);
+  if (h == NULL)
+    error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
+	   dlerror ());
+
+  fp = dlsym (h, "obj1func1");
+  if (fp == NULL)
+    error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s",
+	   "testobj1.so", dlerror ());
+
+  res = fp (10);
+  printf ("fp(10) = %d\n", res);
+
+  if (dlclose (h) != 0)
+    error (EXIT_FAILURE, 0, "while close `%s': %s",
+	   "testobj1.so", dlerror ());
+
+  return res != 42;
+}
+
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return a + 10;
+}
diff --git a/REORG.TODO/elf/pathoptobj.c b/REORG.TODO/elf/pathoptobj.c
new file mode 100644
index 0000000000..a452c2d7d4
--- /dev/null
+++ b/REORG.TODO/elf/pathoptobj.c
@@ -0,0 +1,8 @@
+extern int in_renamed (int);
+
+
+int
+in_renamed (int a)
+{
+  return a - 10;
+}
diff --git a/REORG.TODO/elf/pldd-xx.c b/REORG.TODO/elf/pldd-xx.c
new file mode 100644
index 0000000000..5ce0bce4c9
--- /dev/null
+++ b/REORG.TODO/elf/pldd-xx.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define E(name) E_(name, CLASS)
+#define E_(name, cl) E__(name, cl)
+#define E__(name, cl) name##cl
+#define EW(type) EW_(Elf, CLASS, type)
+#define EW_(e, w, t) EW__(e, w, _##t)
+#define EW__(e, w, t) e##w##t
+
+#define pldd_assert(name, exp) \
+  typedef int __assert_##name[((exp) != 0) - 1]
+
+
+struct E(link_map)
+{
+  EW(Addr) l_addr;
+  EW(Addr) l_name;
+  EW(Addr) l_ld;
+  EW(Addr) l_next;
+  EW(Addr) l_prev;
+  EW(Addr) l_real;
+  Lmid_t l_ns;
+  EW(Addr) l_libname;
+};
+#if CLASS == __ELF_NATIVE_CLASS
+pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
+			== offsetof (struct E(link_map), l_addr)));
+pldd_assert (l_name, (offsetof (struct link_map, l_name)
+			== offsetof (struct E(link_map), l_name)));
+pldd_assert (l_next, (offsetof (struct link_map, l_next)
+			== offsetof (struct E(link_map), l_next)));
+#endif
+
+
+struct E(libname_list)
+{
+  EW(Addr) name;
+  EW(Addr) next;
+};
+#if CLASS == __ELF_NATIVE_CLASS
+pldd_assert (name, (offsetof (struct libname_list, name)
+		      == offsetof (struct E(libname_list), name)));
+pldd_assert (next, (offsetof (struct libname_list, next)
+		      == offsetof (struct E(libname_list), next)));
+#endif
+
+struct E(r_debug)
+{
+  int r_version;
+#if CLASS == 64
+  int pad;
+#endif
+  EW(Addr) r_map;
+};
+#if CLASS == __ELF_NATIVE_CLASS
+pldd_assert (r_version, (offsetof (struct r_debug, r_version)
+			   == offsetof (struct E(r_debug), r_version)));
+pldd_assert (r_map, (offsetof (struct r_debug, r_map)
+		       == offsetof (struct E(r_debug), r_map)));
+#endif
+
+
+static int
+
+E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
+{
+  EW(Addr) phdr = 0;
+  unsigned int phnum = 0;
+  unsigned int phent = 0;
+
+  EW(auxv_t) *auxvXX = (EW(auxv_t) *) auxv;
+  for (int i = 0; i < auxv_size / sizeof (EW(auxv_t)); ++i)
+    switch (auxvXX[i].a_type)
+      {
+      case AT_PHDR:
+	phdr = auxvXX[i].a_un.a_val;
+	break;
+      case AT_PHNUM:
+	phnum = auxvXX[i].a_un.a_val;
+	break;
+      case AT_PHENT:
+	phent = auxvXX[i].a_un.a_val;
+	break;
+      default:
+	break;
+      }
+
+  if (phdr == 0 || phnum == 0 || phent == 0)
+    error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
+
+  EW(Phdr) *p = alloca (phnum * phent);
+  if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
+    {
+      error (0, 0, gettext ("cannot read program header"));
+      return EXIT_FAILURE;
+    }
+
+  /* Determine the load offset.  We need this for interpreting the
+     other program header entries so we do this in a separate loop.
+     Fortunately it is the first time unless someone does something
+     stupid when linking the application.  */
+  EW(Addr) offset = 0;
+  for (unsigned int i = 0; i < phnum; ++i)
+    if (p[i].p_type == PT_PHDR)
+      {
+	offset = phdr - p[i].p_vaddr;
+	break;
+      }
+
+  EW(Addr) list = 0;
+  char *interp = NULL;
+  for (unsigned int i = 0; i < phnum; ++i)
+    if (p[i].p_type == PT_DYNAMIC)
+      {
+	EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
+	if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
+	    != p[i].p_filesz)
+	  {
+	    error (0, 0, gettext ("cannot read dynamic section"));
+	    return EXIT_FAILURE;
+	  }
+
+	/* Search for the DT_DEBUG entry.  */
+	for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
+	  if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
+	    {
+	      struct E(r_debug) r;
+	      if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
+		  != sizeof (r))
+		{
+		  error (0, 0, gettext ("cannot read r_debug"));
+		  return EXIT_FAILURE;
+		}
+
+	      if (r.r_map != 0)
+		{
+		  list = r.r_map;
+		  break;
+		}
+	    }
+
+	free (dyn);
+	break;
+      }
+    else if (p[i].p_type == PT_INTERP)
+      {
+	interp = alloca (p[i].p_filesz);
+	if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
+	    != p[i].p_filesz)
+	  {
+	    error (0, 0, gettext ("cannot read program interpreter"));
+	    return EXIT_FAILURE;
+	  }
+      }
+
+  if (list == 0)
+    {
+      if (interp == NULL)
+	{
+	  // XXX check whether the executable itself is the loader
+	  return EXIT_FAILURE;
+	}
+
+      // XXX perhaps try finding ld.so and _r_debug in it
+
+      return EXIT_FAILURE;
+    }
+
+  /* Print the PID and program name first.  */
+  printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
+
+  /* Iterate over the list of objects and print the information.  */
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
+  int status = 0;
+  do
+    {
+      struct E(link_map) m;
+      if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
+	{
+	  error (0, 0, gettext ("cannot read link map"));
+	  status = EXIT_FAILURE;
+	  goto out;
+	}
+
+      EW(Addr) name_offset = m.l_name;
+    again:
+      while (1)
+	{
+	  ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
+	  if (n == -1)
+	    {
+	      error (0, 0, gettext ("cannot read object name"));
+	      status = EXIT_FAILURE;
+	      goto out;
+	    }
+
+	  if (memchr (tmpbuf.data, '\0', n) != NULL)
+	    break;
+
+	  if (!scratch_buffer_grow (&tmpbuf))
+	    {
+	      error (0, 0, gettext ("cannot allocate buffer for object name"));
+	      status = EXIT_FAILURE;
+	      goto out;
+	    }
+	}
+
+      if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
+	  && m.l_libname != 0)
+	{
+	  /* Try the l_libname element.  */
+	  struct E(libname_list) ln;
+	  if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
+	    {
+	      name_offset = ln.name;
+	      goto again;
+	    }
+	}
+
+      /* Skip over the executable.  */
+      if (((char *)tmpbuf.data)[0] != '\0')
+	printf ("%s\n", (char *)tmpbuf.data);
+
+      list = m.l_next;
+    }
+  while (list != 0);
+
+ out:
+  scratch_buffer_free (&tmpbuf);
+  return status;
+}
+
+
+#undef CLASS
diff --git a/REORG.TODO/elf/pldd.c b/REORG.TODO/elf/pldd.c
new file mode 100644
index 0000000000..ddfa88d63b
--- /dev/null
+++ b/REORG.TODO/elf/pldd.c
@@ -0,0 +1,344 @@
+/* List dynamic shared objects linked into given process.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <alloca.h>
+#include <argp.h>
+#include <assert.h>
+#include <dirent.h>
+#include <elf.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <link.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <scratch_buffer.h>
+
+#include <ldsodefs.h>
+#include <version.h>
+
+/* Global variables.  */
+extern char *program_invocation_short_name;
+#define PACKAGE _libc_intl_domainname
+
+/* External functions.  */
+#include <programs/xmalloc.h>
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, NULL }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+List dynamic shared objects loaded into process.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("PID");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, more_help, NULL
+};
+
+// File descriptor of /proc/*/mem file.
+static int memfd;
+
+/* Name of the executable  */
+static char *exe;
+
+/* Local functions.  */
+static int get_process_info (int dfd, long int pid);
+static void wait_for_ptrace_stop (long int pid);
+
+
+int
+main (int argc, char *argv[])
+{
+  /* Parse and process arguments.  */
+  int remaining;
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  if (remaining != argc - 1)
+    {
+      fprintf (stderr,
+	       gettext ("Exactly one parameter with process ID required.\n"));
+      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
+      return 1;
+    }
+
+  assert (sizeof (pid_t) == sizeof (int)
+	  || sizeof (pid_t) == sizeof (long int));
+  char *endp;
+  errno = 0;
+  long int pid = strtol (argv[remaining], &endp, 10);
+  if (pid < 0 || (pid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
+      || (sizeof (pid_t) < sizeof (pid) && pid > INT_MAX))
+    error (EXIT_FAILURE, 0, gettext ("invalid process ID '%s'"),
+	   argv[remaining]);
+
+  /* Determine the program name.  */
+  char buf[7 + 3 * sizeof (pid)];
+  snprintf (buf, sizeof (buf), "/proc/%lu", pid);
+  int dfd = open (buf, O_RDONLY | O_DIRECTORY);
+  if (dfd == -1)
+    error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
+
+  struct scratch_buffer exebuf;
+  scratch_buffer_init (&exebuf);
+  ssize_t nexe;
+  while ((nexe = readlinkat (dfd, "exe",
+			     exebuf.data, exebuf.length)) == exebuf.length)
+    {
+      if (!scratch_buffer_grow (&exebuf))
+	{
+	  nexe = -1;
+	  break;
+	}
+    }
+  if (nexe == -1)
+    exe = (char *) "<program name undetermined>";
+  else
+    {
+      exe = exebuf.data;
+      exe[nexe] = '\0';
+    }
+
+  /* Stop all threads since otherwise the list of loaded modules might
+     change while we are reading it.  */
+  struct thread_list
+  {
+    pid_t tid;
+    struct thread_list *next;
+  } *thread_list = NULL;
+
+  int taskfd = openat (dfd, "task", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+  if (taskfd == 1)
+    error (EXIT_FAILURE, errno, gettext ("cannot open %s/task"), buf);
+  DIR *dir = fdopendir (taskfd);
+  if (dir == NULL)
+    error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
+	   buf);
+
+  struct dirent64 *d;
+  while ((d = readdir64 (dir)) != NULL)
+    {
+      if (! isdigit (d->d_name[0]))
+	continue;
+
+      errno = 0;
+      long int tid = strtol (d->d_name, &endp, 10);
+      if (tid < 0 || (tid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
+	  || (sizeof (pid_t) < sizeof (pid) && tid > INT_MAX))
+	error (EXIT_FAILURE, 0, gettext ("invalid thread ID '%s'"),
+	       d->d_name);
+
+      if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
+	{
+	  /* There might be a race between reading the directory and
+	     threads terminating.  Ignore errors attaching to unknown
+	     threads unless this is the main thread.  */
+	  if (errno == ESRCH && tid != pid)
+	    continue;
+
+	  error (EXIT_FAILURE, errno, gettext ("cannot attach to process %lu"),
+		 tid);
+	}
+
+      wait_for_ptrace_stop (tid);
+
+      struct thread_list *newp = alloca (sizeof (*newp));
+      newp->tid = tid;
+      newp->next = thread_list;
+      thread_list = newp;
+    }
+
+  closedir (dir);
+
+  int status = get_process_info (dfd, pid);
+
+  assert (thread_list != NULL);
+  do
+    {
+      ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
+      thread_list = thread_list->next;
+    }
+  while (thread_list != NULL);
+
+  close (dfd);
+
+  return status;
+}
+
+
+/* Wait for PID to enter ptrace-stop state after being attached.  */
+static void
+wait_for_ptrace_stop (long int pid)
+{
+  int status;
+
+  /* While waiting for SIGSTOP being delivered to the tracee we have to
+     reinject any other pending signal.  Ignore all other errors.  */
+  while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status))
+    {
+      /* The STOP signal should not be delivered to the tracee.  */
+      if (WSTOPSIG (status) == SIGSTOP)
+	return;
+      if (ptrace (PTRACE_CONT, pid, NULL,
+		  (void *) (uintptr_t) WSTOPSIG (status)))
+	/* The only possible error is that the process died.  */
+	return;
+    }
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Print bug-reporting information in the help message.  */
+static char *
+more_help (int key, const char *text, void *input)
+{
+  char *tp = NULL;
+  switch (key)
+    {
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      if (asprintf (&tp, gettext ("\
+For bug reporting instructions, please see:\n\
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
+    default:
+      break;
+    }
+  return (char *) text;
+}
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "pldd %s%s\n", PKGVERSION, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "2017");
+  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
+}
+
+
+#define CLASS 32
+#include "pldd-xx.c"
+#define CLASS 64
+#include "pldd-xx.c"
+
+
+static int
+get_process_info (int dfd, long int pid)
+{
+  memfd = openat (dfd, "mem", O_RDONLY);
+  if (memfd == -1)
+    goto no_info;
+
+  int fd = openat (dfd, "exe", O_RDONLY);
+  if (fd == -1)
+    {
+    no_info:
+      error (0, errno, gettext ("cannot get information about process %lu"),
+	     pid);
+      return EXIT_FAILURE;
+    }
+
+  char e_ident[EI_NIDENT];
+  if (read (fd, e_ident, EI_NIDENT) != EI_NIDENT)
+    goto no_info;
+
+  close (fd);
+
+  if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
+    {
+      error (0, 0, gettext ("process %lu is no ELF program"), pid);
+      return EXIT_FAILURE;
+    }
+
+  fd = openat (dfd, "auxv", O_RDONLY);
+  if (fd == -1)
+    goto no_info;
+
+  size_t auxv_size = 0;
+  void *auxv = NULL;
+  while (1)
+    {
+      auxv_size += 512;
+      auxv = xrealloc (auxv, auxv_size);
+
+      ssize_t n = pread (fd, auxv, auxv_size, 0);
+      if (n < 0)
+	goto no_info;
+      if (n < auxv_size)
+	{
+	  auxv_size = n;
+	  break;
+	}
+    }
+
+  close (fd);
+
+  int retval;
+  if (e_ident[EI_CLASS] == ELFCLASS32)
+    retval = find_maps32 (pid, auxv, auxv_size);
+  else
+    retval = find_maps64 (pid, auxv, auxv_size);
+
+  free (auxv);
+  close (memfd);
+
+  return retval;
+}
diff --git a/REORG.TODO/elf/preloadtest.c b/REORG.TODO/elf/preloadtest.c
new file mode 100644
index 0000000000..7ea10b9b5b
--- /dev/null
+++ b/REORG.TODO/elf/preloadtest.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+#include "testobj.h"
+
+int
+main (void)
+{
+  int res = preload (42);
+
+  printf ("preload (42) = %d, %s\n", res, res == 92 ? "ok" : "wrong");
+
+  return res != 92;
+}
+
+int
+foo (int a)
+{
+  return a;
+}
diff --git a/REORG.TODO/elf/readelflib.c b/REORG.TODO/elf/readelflib.c
new file mode 100644
index 0000000000..9ad56dcc34
--- /dev/null
+++ b/REORG.TODO/elf/readelflib.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
+		  Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This code is a heavily simplified version of the readelf program
+   that's part of the current binutils development version.  For architectures
+   which need to handle both 32bit and 64bit ELF libraries,  this file is
+   included twice for each arch size.  */
+
+/* check_ptr checks that a pointer is in the mmaped file and doesn't
+   point outside it.  */
+#undef check_ptr
+#define check_ptr(ptr)						\
+do								\
+  {								\
+    if ((void *)(ptr) < file_contents				\
+	|| (void *)(ptr) > (file_contents+file_length))		\
+      {								\
+	error (0, 0, _("file %s is truncated\n"), file_name);	\
+	return 1;						\
+      }								\
+  }								\
+ while (0);
+
+/* Returns 0 if everything is ok, != 0 in case of error.  */
+int
+process_elf_file (const char *file_name, const char *lib, int *flag,
+		  unsigned int *osversion, char **soname, void *file_contents,
+		  size_t file_length)
+{
+  int i;
+  unsigned int j;
+  ElfW(Addr) loadaddr;
+  unsigned int dynamic_addr;
+  size_t dynamic_size;
+  char *program_interpreter;
+
+  ElfW(Ehdr) *elf_header;
+  ElfW(Phdr) *elf_pheader, *segment;
+  ElfW(Dyn) *dynamic_segment, *dyn_entry;
+  char *dynamic_strings;
+
+  elf_header = (ElfW(Ehdr) *) file_contents;
+  *osversion = 0;
+
+  if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS))
+    {
+      if (opt_verbose)
+	{
+	  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
+	    error (0, 0, _("%s is a 32 bit ELF file.\n"), file_name);
+	  else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
+	    error (0, 0, _("%s is a 64 bit ELF file.\n"), file_name);
+	  else
+	    error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
+	}
+      return 1;
+    }
+
+  if (elf_header->e_type != ET_DYN)
+    {
+      error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
+	     elf_header->e_type);
+      return 1;
+    }
+
+  /* Get information from elf program header.  */
+  elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents);
+  check_ptr (elf_pheader);
+
+  /* The library is an elf library, now search for soname and
+     libc5/libc6.  */
+  *flag = FLAG_ELF;
+
+  loadaddr = -1;
+  dynamic_addr = 0;
+  dynamic_size = 0;
+  program_interpreter = NULL;
+  for (i = 0, segment = elf_pheader;
+       i < elf_header->e_phnum; i++, segment++)
+    {
+      check_ptr (segment);
+
+      switch (segment->p_type)
+	{
+	case PT_LOAD:
+	  if (loadaddr == (ElfW(Addr)) -1)
+	    loadaddr = segment->p_vaddr - segment->p_offset;
+	  break;
+
+	case PT_DYNAMIC:
+	  if (dynamic_addr)
+	    error (0, 0, _("more than one dynamic segment\n"));
+
+	  dynamic_addr = segment->p_offset;
+	  dynamic_size = segment->p_filesz;
+	  break;
+
+	case PT_INTERP:
+	  program_interpreter = (char *) (file_contents + segment->p_offset);
+	  check_ptr (program_interpreter);
+
+	  /* Check if this is enough to classify the binary.  */
+	  for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]);
+	       ++j)
+	    if (strcmp (program_interpreter, interpreters[j].soname) == 0)
+	      {
+		*flag = interpreters[j].flag;
+		break;
+	      }
+	  break;
+
+	case PT_NOTE:
+	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
+	    {
+	      ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
+						     + segment->p_offset);
+	      ElfW(Addr) size = segment->p_filesz;
+
+	      while (abi_note [0] != 4 || abi_note [1] != 16
+		     || abi_note [2] != 1
+		     || memcmp (abi_note + 3, "GNU", 4) != 0)
+		{
+#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+		  ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
+					 + ROUND (abi_note[0])
+					 + ROUND (abi_note[1]);
+
+		  if (size - 32 < note_size || note_size == 0)
+		    {
+		      size = 0;
+		      break;
+		    }
+		  size -= note_size;
+		  abi_note = (void *) abi_note + note_size;
+		}
+
+	      if (size == 0)
+		break;
+
+	      *osversion = (abi_note [4] << 24) |
+			   ((abi_note [5] & 0xff) << 16) |
+			   ((abi_note [6] & 0xff) << 8) |
+			   (abi_note [7] & 0xff);
+	    }
+	  break;
+
+	default:
+	  break;
+	}
+
+    }
+  if (loadaddr == (ElfW(Addr)) -1)
+    {
+      /* Very strange. */
+      loadaddr = 0;
+    }
+
+  /* Now we can read the dynamic sections.  */
+  if (dynamic_size == 0)
+    return 1;
+
+  dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr);
+  check_ptr (dynamic_segment);
+
+  /* Find the string table.  */
+  dynamic_strings = NULL;
+  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
+       ++dyn_entry)
+    {
+      check_ptr (dyn_entry);
+      if (dyn_entry->d_tag == DT_STRTAB)
+	{
+	  dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
+	  check_ptr (dynamic_strings);
+	  break;
+	}
+    }
+
+  if (dynamic_strings == NULL)
+    return 1;
+
+  /* Now read the DT_NEEDED and DT_SONAME entries.  */
+  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
+       ++dyn_entry)
+    {
+      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
+	{
+	  char *name = dynamic_strings + dyn_entry->d_un.d_val;
+	  check_ptr (name);
+
+	  if (dyn_entry->d_tag == DT_NEEDED)
+	    {
+
+	      if (*flag == FLAG_ELF)
+		{
+		  /* Check if this is enough to classify the binary.  */
+		  for (j = 0;
+		       j < sizeof (known_libs) / sizeof (known_libs [0]);
+		       ++j)
+		    if (strcmp (name, known_libs [j].soname) == 0)
+		      {
+			*flag = known_libs [j].flag;
+			break;
+		      }
+		}
+	    }
+
+	  else if (dyn_entry->d_tag == DT_SONAME)
+	    *soname = xstrdup (name);
+
+	  /* Do we have everything we need?  */
+	  if (*soname && *flag != FLAG_ELF)
+	    return 0;
+	}
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/readlib.c b/REORG.TODO/elf/readlib.c
new file mode 100644
index 0000000000..d278a189b2
--- /dev/null
+++ b/REORG.TODO/elf/readlib.c
@@ -0,0 +1,212 @@
+/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
+		  Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* The code in this file and in readelflib is a heavily simplified
+   version of the readelf program that's part of the current binutils
+   development version.  Besides the simplification, it has also been
+   modified to read some other file formats.  */
+
+#include <a.out.h>
+#include <elf.h>
+#include <error.h>
+#include <libintl.h>
+#include <link.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <gnu/lib-names.h>
+
+#include <ldconfig.h>
+
+#define Elf32_CLASS ELFCLASS32
+#define Elf64_CLASS ELFCLASS64
+
+struct known_names
+{
+  const char *soname;
+  int flag;
+};
+
+static struct known_names interpreters[] =
+{
+  { "/lib/" LD_SO, FLAG_ELF_LIBC6 },
+#ifdef SYSDEP_KNOWN_INTERPRETER_NAMES
+  SYSDEP_KNOWN_INTERPRETER_NAMES
+#endif
+};
+
+static struct known_names known_libs[] =
+{
+  { LIBC_SO, FLAG_ELF_LIBC6 },
+  { LIBM_SO, FLAG_ELF_LIBC6 },
+#ifdef SYSDEP_KNOWN_LIBRARY_NAMES
+  SYSDEP_KNOWN_LIBRARY_NAMES
+#endif
+};
+
+
+/* Check if string corresponds to a GDB Python file.  */
+static bool
+is_gdb_python_file (const char *name)
+{
+  size_t len = strlen (name);
+  return len > 7 && strcmp (name + len - 7, "-gdb.py") == 0;
+}
+
+/* Returns 0 if everything is ok, != 0 in case of error.  */
+int
+process_file (const char *real_file_name, const char *file_name,
+	      const char *lib, int *flag, unsigned int *osversion,
+	      char **soname, int is_link, struct stat64 *stat_buf)
+{
+  FILE *file;
+  struct stat64 statbuf;
+  void *file_contents;
+  int ret;
+  ElfW(Ehdr) *elf_header;
+  struct exec *aout_header;
+
+  ret = 0;
+  *flag = FLAG_ANY;
+  *soname = NULL;
+
+  file = fopen (real_file_name, "rb");
+  if (file == NULL)
+    {
+      /* No error for stale symlink.  */
+      if (is_link && strstr (file_name, ".so") != NULL)
+	return 1;
+      error (0, 0, _("Input file %s not found.\n"), file_name);
+      return 1;
+    }
+
+  if (fstat64 (fileno (file), &statbuf) < 0)
+    {
+      error (0, 0, _("Cannot fstat file %s.\n"), file_name);
+      fclose (file);
+      return 1;
+    }
+
+  /* Check that the file is large enough so that we can access the
+     information.  We're only checking the size of the headers here.  */
+  if ((size_t) statbuf.st_size < sizeof (struct exec)
+      || (size_t) statbuf.st_size < sizeof (ElfW(Ehdr)))
+    {
+      if (statbuf.st_size == 0)
+	error (0, 0, _("File %s is empty, not checked."), file_name);
+      else
+	{
+	  char buf[SELFMAG];
+	  size_t n = MIN (statbuf.st_size, SELFMAG);
+	  if (fread (buf, n, 1, file) == 1 && memcmp (buf, ELFMAG, n) == 0)
+	    error (0, 0, _("File %s is too small, not checked."), file_name);
+	}
+      fclose (file);
+      return 1;
+    }
+
+  file_contents = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED,
+			fileno (file), 0);
+  if (file_contents == MAP_FAILED)
+    {
+      error (0, 0, _("Cannot mmap file %s.\n"), file_name);
+      fclose (file);
+      return 1;
+    }
+
+  /* First check if this is an aout file.  */
+  aout_header = (struct exec *) file_contents;
+  if (N_MAGIC (*aout_header) == ZMAGIC
+#ifdef QMAGIC			/* Linuxism.  */
+      || N_MAGIC (*aout_header) == QMAGIC
+#endif
+      )
+    {
+      /* Aout files don't have a soname, just return the name
+	 including the major number.  */
+      char *copy, *major, *dot;
+      copy = xstrdup (lib);
+      major = strstr (copy, ".so.");
+      if (major)
+	{
+	  dot = strstr (major + 4, ".");
+	  if (dot)
+	    *dot = '\0';
+	}
+      *soname = copy;
+      *flag = FLAG_LIBC4;
+      goto done;
+    }
+
+  elf_header = (ElfW(Ehdr) *) file_contents;
+  if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG) != 0)
+    {
+      /* The file is neither ELF nor aout.  Check if it's a linker
+	 script, like libc.so - otherwise complain.  Only search the
+	 beginning of the file.  */
+      size_t len = MIN (statbuf.st_size, 512);
+      if (memmem (file_contents, len, "GROUP", 5) == NULL
+	  && memmem (file_contents, len, "GNU ld script", 13) == NULL
+	  && !is_gdb_python_file (file_name))
+	error (0, 0, _("%s is not an ELF file - it has the wrong magic bytes at the start.\n"),
+	       file_name);
+      ret = 1;
+    }
+  /* Libraries have to be shared object files.  */
+  else if (elf_header->e_type != ET_DYN)
+    ret = 1;
+  else if (process_elf_file (file_name, lib, flag, osversion, soname,
+			     file_contents, statbuf.st_size))
+    ret = 1;
+
+ done:
+  /* Clean up allocated memory and resources.  */
+  munmap (file_contents, statbuf.st_size);
+  fclose (file);
+
+  *stat_buf = statbuf;
+  return ret;
+}
+
+/* Returns made up soname if lib doesn't have explicit DT_SONAME.  */
+
+char *
+implicit_soname (const char *lib, int flag)
+{
+  char *soname = xstrdup (lib);
+
+  if ((flag & FLAG_TYPE_MASK) != FLAG_LIBC4)
+    return soname;
+
+  /* Aout files don't have a soname, just return the name
+     including the major number.  */
+  char *major = strstr (soname, ".so.");
+  if (major)
+    {
+      char *dot = strstr (major + 4, ".");
+      if (dot)
+	*dot = '\0';
+    }
+  return soname;
+}
+
+/* Get architecture specific version of process_elf_file.  */
+#include <readelflib.c>
diff --git a/REORG.TODO/elf/reldep.c b/REORG.TODO/elf/reldep.c
new file mode 100644
index 0000000000..adabc0d5d5
--- /dev/null
+++ b/REORG.TODO/elf/reldep.c
@@ -0,0 +1,111 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod2.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  If must still be around since we have
+     an implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Try calling the function again.  This will fail if the first object
+     got unloaded.  */
+  if (fp () != 0)
+    {
+      puts ("second call of function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the second file as well.  */
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Finally, open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* And get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+	      dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 0)
+    {
+      puts ("variable \"some_var\" not reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep2.c b/REORG.TODO/elf/reldep2.c
new file mode 100644
index 0000000000..ba5ab222f9
--- /dev/null
+++ b/REORG.TODO/elf/reldep2.c
@@ -0,0 +1,101 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod3.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod3.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  It must still be around since we have
+     an implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+	      dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 42)
+    {
+      puts ("variable \"some_var\" reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep3.c b/REORG.TODO/elf/reldep3.c
new file mode 100644
index 0000000000..05013d3509
--- /dev/null
+++ b/REORG.TODO/elf/reldep3.c
@@ -0,0 +1,101 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod4.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod4.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  If must still be around since we have
+     an implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+	      dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 0)
+    {
+      puts ("variable \"some_var\" not reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep4.c b/REORG.TODO/elf/reldep4.c
new file mode 100644
index 0000000000..ba12e7d9c4
--- /dev/null
+++ b/REORG.TODO/elf/reldep4.c
@@ -0,0 +1,40 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int i;
+  void *h1, *h2;
+
+  mtrace ();
+
+  for (i = 0; i < 3; i++)
+    {
+      h1 = dlopen ("reldep4mod1.so", RTLD_NOW | RTLD_GLOBAL);
+      if (h1 == NULL)
+	{
+	  printf ("cannot open reldep4mod1.so: %s\n", dlerror ());
+	  exit (1);
+	}
+      h2 = dlopen ("reldep4mod2.so", RTLD_NOW | RTLD_GLOBAL);
+      if (h2 == NULL)
+	{
+	  printf ("cannot open reldep4mod2.so: %s\n", dlerror ());
+	  exit (1);
+	}
+      if (dlclose (h1) != 0)
+	{
+	  printf ("closing h1 failed: %s\n", dlerror ());
+	  exit (1);
+	}
+      if (dlclose (h2) != 0)
+	{
+	  printf ("closing h2 failed: %s\n", dlerror ());
+	  exit (1);
+	}
+    }
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep4mod1.c b/REORG.TODO/elf/reldep4mod1.c
new file mode 100644
index 0000000000..934a68096e
--- /dev/null
+++ b/REORG.TODO/elf/reldep4mod1.c
@@ -0,0 +1,7 @@
+int foo (void);
+
+int foo (void)
+{
+  return 0;
+}
+
diff --git a/REORG.TODO/elf/reldep4mod2.c b/REORG.TODO/elf/reldep4mod2.c
new file mode 100644
index 0000000000..26ce6bf13a
--- /dev/null
+++ b/REORG.TODO/elf/reldep4mod2.c
@@ -0,0 +1,8 @@
+extern int foo (void);
+extern int bar (void);
+
+int
+bar (void)
+{
+  return foo ();
+}
diff --git a/REORG.TODO/elf/reldep4mod3.c b/REORG.TODO/elf/reldep4mod3.c
new file mode 100644
index 0000000000..934a68096e
--- /dev/null
+++ b/REORG.TODO/elf/reldep4mod3.c
@@ -0,0 +1,7 @@
+int foo (void);
+
+int foo (void)
+{
+  return 0;
+}
+
diff --git a/REORG.TODO/elf/reldep4mod4.c b/REORG.TODO/elf/reldep4mod4.c
new file mode 100644
index 0000000000..26ce6bf13a
--- /dev/null
+++ b/REORG.TODO/elf/reldep4mod4.c
@@ -0,0 +1,8 @@
+extern int foo (void);
+extern int bar (void);
+
+int
+bar (void)
+{
+  return foo ();
+}
diff --git a/REORG.TODO/elf/reldep5.c b/REORG.TODO/elf/reldep5.c
new file mode 100644
index 0000000000..881d519ff6
--- /dev/null
+++ b/REORG.TODO/elf/reldep5.c
@@ -0,0 +1,70 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod5.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod5.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod6.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod6.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  fp = dlsym (h2, "bar");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"bar\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  puts ("calling fp for the first time");
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  It must still be around since we have
+     an implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Calling the function must still work.  */
+  puts ("calling fp for the second time");
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" the second time returned wrong result");
+      exit (1);
+    }
+  puts ("second call suceeded as well");
+
+  /* Close the second object, we are done.  */
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep6.c b/REORG.TODO/elf/reldep6.c
new file mode 100644
index 0000000000..1eeec6c862
--- /dev/null
+++ b/REORG.TODO/elf/reldep6.c
@@ -0,0 +1,109 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef int (*fn)(void);
+#define CHUNKS 1024
+#define REPEAT 64
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  fn **foopp;
+  fn bar, baz;
+  int i, j;
+  int n;
+  void *allocs[REPEAT][CHUNKS];
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldep6mod3.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldep6mod3.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  foopp = dlsym (h1, "foopp");
+  if (foopp == NULL)
+    {
+      printf ("cannot get address of \"foopp\": %s\n", dlerror ());
+      exit (1);
+    }
+  n = (**foopp) ();
+  if (n != 20)
+    {
+      printf ("(**foopp)() return %d, not return 20\n", n);
+      exit (1);
+    }
+
+  h2 = dlopen ("reldep6mod4.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldep6mod4.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  baz = dlsym (h2, "baz");
+  if (baz == NULL)
+    {
+      printf ("cannot get address of \"baz\": %s\n", dlerror ());
+      exit (1);
+    }
+  if (baz () != 31)
+    {
+      printf ("baz() did not return 31\n");
+      exit (1);
+    }
+
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Clobber memory.  */
+  for (i = 0; i < REPEAT; ++i)
+    for (j = 0; j < CHUNKS; ++j)
+      allocs[i][j] = calloc (1, j + 1);
+
+  bar = dlsym (h2, "bar");
+  if (bar == NULL)
+    {
+      printf ("cannot get address of \"bar\": %s\n", dlerror ());
+      exit (1);
+    }
+  if (bar () != 40)
+    {
+      printf ("bar() did not return 40\n");
+      exit (1);
+    }
+
+  baz = dlsym (h2, "baz");
+  if (baz == NULL)
+    {
+      printf ("cannot get address of \"baz\": %s\n", dlerror ());
+      exit (1);
+    }
+  if (baz () != 31)
+    {
+      printf ("baz() did not return 31\n");
+      exit (1);
+    }
+
+  for (i = 0; i < REPEAT; ++i)
+    for (j = 0; j < CHUNKS; ++j)
+      free (allocs[i][j]);
+
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep6mod0.c b/REORG.TODO/elf/reldep6mod0.c
new file mode 100644
index 0000000000..58f3745fb4
--- /dev/null
+++ b/REORG.TODO/elf/reldep6mod0.c
@@ -0,0 +1,8 @@
+int bar (void);
+extern void free (void *);
+
+int bar (void)
+{
+  free (0);
+  return 40;
+}
diff --git a/REORG.TODO/elf/reldep6mod1.c b/REORG.TODO/elf/reldep6mod1.c
new file mode 100644
index 0000000000..037a73a198
--- /dev/null
+++ b/REORG.TODO/elf/reldep6mod1.c
@@ -0,0 +1,14 @@
+int foo (void);
+int baz (void);
+extern int weak (void);
+asm (".weak weak");
+
+int foo (void)
+{
+  return 20;
+}
+
+int baz (void)
+{
+  return weak () + 1;
+}
diff --git a/REORG.TODO/elf/reldep6mod2.c b/REORG.TODO/elf/reldep6mod2.c
new file mode 100644
index 0000000000..c2ef3f9bc0
--- /dev/null
+++ b/REORG.TODO/elf/reldep6mod2.c
@@ -0,0 +1,3 @@
+extern int foo (void);
+
+void *foop = (void *) foo;
diff --git a/REORG.TODO/elf/reldep6mod3.c b/REORG.TODO/elf/reldep6mod3.c
new file mode 100644
index 0000000000..881828ef6e
--- /dev/null
+++ b/REORG.TODO/elf/reldep6mod3.c
@@ -0,0 +1,3 @@
+extern void *foop;
+
+void **foopp = &foop;
diff --git a/REORG.TODO/elf/reldep6mod4.c b/REORG.TODO/elf/reldep6mod4.c
new file mode 100644
index 0000000000..8fa89de64b
--- /dev/null
+++ b/REORG.TODO/elf/reldep6mod4.c
@@ -0,0 +1,12 @@
+int foo (void);
+int weak (void);
+
+int foo (void)
+{
+  return 10;
+}
+
+int weak (void)
+{
+  return 30;
+}
diff --git a/REORG.TODO/elf/reldep7.c b/REORG.TODO/elf/reldep7.c
new file mode 100644
index 0000000000..5275a0e8f1
--- /dev/null
+++ b/REORG.TODO/elf/reldep7.c
@@ -0,0 +1,58 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  void *mod1_bar, *mod2_bar;
+
+  h1 = dlopen ("reldep7mod1.so", RTLD_GLOBAL | RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldep7mod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  h2 = dlopen ("reldep7mod2.so", RTLD_GLOBAL | RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldep7mod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  mod1_bar = dlsym (h1, "mod1_bar");
+  if (mod1_bar == NULL)
+    {
+      printf ("cannot get address of \"mod1_bar\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  mod2_bar = dlsym (h2, "mod2_bar");
+  if (mod2_bar == NULL)
+    {
+      printf ("cannot get address of \"mod2_bar\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  printf ("%d\n", ((int (*) (void)) mod1_bar) ());
+  printf ("%d\n", ((int (*) (void)) mod2_bar) ());
+
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  printf ("%d\n", ((int (*) (void)) mod2_bar) ());
+
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/reldep7mod1.c b/REORG.TODO/elf/reldep7mod1.c
new file mode 100644
index 0000000000..de1bb3a6cd
--- /dev/null
+++ b/REORG.TODO/elf/reldep7mod1.c
@@ -0,0 +1,12 @@
+int foo (void) __attribute__ ((weak));
+int
+foo (void)
+{
+  return 1;
+}
+
+int
+mod1_bar (void)
+{
+  return foo ();
+}
diff --git a/REORG.TODO/elf/reldep7mod2.c b/REORG.TODO/elf/reldep7mod2.c
new file mode 100644
index 0000000000..3fa3368792
--- /dev/null
+++ b/REORG.TODO/elf/reldep7mod2.c
@@ -0,0 +1,12 @@
+int foo (void) __attribute__ ((weak));
+int
+foo (void)
+{
+  return 2;
+}
+
+int
+mod2_bar (void)
+{
+  return foo ();
+}
diff --git a/REORG.TODO/elf/reldep8.c b/REORG.TODO/elf/reldep8.c
new file mode 100644
index 0000000000..90009a5609
--- /dev/null
+++ b/REORG.TODO/elf/reldep8.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+int
+main (void)
+{
+  void *handle = dlopen ("reldep8mod3.so", RTLD_LAZY);
+  if (handle == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  dlclose (handle);
+  abort ();
+}
diff --git a/REORG.TODO/elf/reldep8mod1.c b/REORG.TODO/elf/reldep8mod1.c
new file mode 100644
index 0000000000..acddc4cf8b
--- /dev/null
+++ b/REORG.TODO/elf/reldep8mod1.c
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+void
+foo (void)
+{
+  exit (0);
+}
+
+void
+__attribute__((destructor))
+bar (void)
+{
+  static int i;
+  foo ();
+  ++i;
+}
+void
+baz (void)
+{
+}
diff --git a/REORG.TODO/elf/reldep8mod2.c b/REORG.TODO/elf/reldep8mod2.c
new file mode 100644
index 0000000000..d0020240a8
--- /dev/null
+++ b/REORG.TODO/elf/reldep8mod2.c
@@ -0,0 +1,7 @@
+void
+__attribute__((constructor))
+xxx (void)
+{
+  extern void baz (void);
+  baz ();
+}
diff --git a/REORG.TODO/elf/reldep8mod3.c b/REORG.TODO/elf/reldep8mod3.c
new file mode 100644
index 0000000000..6d1a0d47b7
--- /dev/null
+++ b/REORG.TODO/elf/reldep8mod3.c
@@ -0,0 +1 @@
+int x;
diff --git a/REORG.TODO/elf/reldep9.c b/REORG.TODO/elf/reldep9.c
new file mode 100644
index 0000000000..51c7a8bb9e
--- /dev/null
+++ b/REORG.TODO/elf/reldep9.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+int
+main (void)
+{
+  void *handle = dlopen ("reldep9mod3.so", RTLD_LAZY);
+  if (handle == NULL)
+    {
+      printf ("%s\n", dlerror ());
+      exit (1);
+    }
+  dlclose (handle);
+  abort ();
+}
diff --git a/REORG.TODO/elf/reldep9mod1.c b/REORG.TODO/elf/reldep9mod1.c
new file mode 100644
index 0000000000..249a2bae1c
--- /dev/null
+++ b/REORG.TODO/elf/reldep9mod1.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+void
+foo (void)
+{
+  exit (0);
+}
+
+void
+__attribute__((destructor))
+bar (void)
+{
+  static int i;
+  foo ();
+  ++i;
+}
+
+void
+__attribute__((constructor))
+destr (void)
+{
+  extern void baz (void);
+  baz ();
+}
diff --git a/REORG.TODO/elf/reldep9mod2.c b/REORG.TODO/elf/reldep9mod2.c
new file mode 100644
index 0000000000..090966e3e3
--- /dev/null
+++ b/REORG.TODO/elf/reldep9mod2.c
@@ -0,0 +1,3 @@
+void baz (void)
+{
+}
diff --git a/REORG.TODO/elf/reldep9mod3.c b/REORG.TODO/elf/reldep9mod3.c
new file mode 100644
index 0000000000..6d1a0d47b7
--- /dev/null
+++ b/REORG.TODO/elf/reldep9mod3.c
@@ -0,0 +1 @@
+int x;
diff --git a/REORG.TODO/elf/reldepmod1.c b/REORG.TODO/elf/reldepmod1.c
new file mode 100644
index 0000000000..b8ef6401e1
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod1.c
@@ -0,0 +1,10 @@
+extern int foo (void);
+
+int some_var;
+
+
+int
+foo (void)
+{
+  return some_var;
+}
diff --git a/REORG.TODO/elf/reldepmod2.c b/REORG.TODO/elf/reldepmod2.c
new file mode 100644
index 0000000000..b7edebae80
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod2.c
@@ -0,0 +1,8 @@
+extern int foo (void);
+extern int call_me (void);
+
+int
+call_me (void)
+{
+  return foo () - 42;
+}
diff --git a/REORG.TODO/elf/reldepmod3.c b/REORG.TODO/elf/reldepmod3.c
new file mode 100644
index 0000000000..66a996cd90
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod3.c
@@ -0,0 +1,20 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int call_me (void);
+
+int
+call_me (void)
+{
+  int (*fp) (void);
+
+  fp = dlsym (RTLD_DEFAULT, "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of foo in global scope: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return fp () - 42;
+}
diff --git a/REORG.TODO/elf/reldepmod4.c b/REORG.TODO/elf/reldepmod4.c
new file mode 100644
index 0000000000..dcb503bba7
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod4.c
@@ -0,0 +1,37 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int call_me (void);
+
+int
+call_me (void)
+{
+  void *h;
+  int (*fp) (void);
+  int res;
+
+  h = dlopen ("reldepmod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open reldepmod1.so in %s: %s\n", __FILE__, dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of foo in global scope: %s\n", dlerror ());
+      exit (1);
+    }
+
+  res = fp () - 42;
+
+  if (dlclose (h) != 0)
+    {
+      printf ("failure when closing h in %s: %s\n", __FILE__, dlerror ());
+      exit (1);
+    }
+
+  return res;
+}
diff --git a/REORG.TODO/elf/reldepmod5.c b/REORG.TODO/elf/reldepmod5.c
new file mode 100644
index 0000000000..62df697162
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod5.c
@@ -0,0 +1,7 @@
+extern int foo (void);
+
+int
+foo (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/reldepmod6.c b/REORG.TODO/elf/reldepmod6.c
new file mode 100644
index 0000000000..cd2aeb400d
--- /dev/null
+++ b/REORG.TODO/elf/reldepmod6.c
@@ -0,0 +1,8 @@
+extern int call_me (void);
+extern int bar (void);
+
+int
+bar (void)
+{
+  return call_me ();
+}
diff --git a/REORG.TODO/elf/resolvfail.c b/REORG.TODO/elf/resolvfail.c
new file mode 100644
index 0000000000..ebd635d153
--- /dev/null
+++ b/REORG.TODO/elf/resolvfail.c
@@ -0,0 +1,31 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+static const char obj[] = "testobj1.so";
+
+int
+main (void)
+{
+  void *d = dlopen (obj, RTLD_LAZY);
+  int n;
+
+  if (d == NULL)
+    {
+      printf ("cannot load %s: %s\n", obj, dlerror ());
+      return 1;
+    }
+
+  for (n = 0; n < 10000; ++n)
+    if (dlsym (d, "does not exist") != NULL)
+      {
+	puts ("dlsym() did not fail");
+	return 1;
+      }
+    else if (dlerror () == NULL)
+      {
+	puts ("dlerror() didn't return a string");
+	return 1;
+      }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/restest1.c b/REORG.TODO/elf/restest1.c
new file mode 100644
index 0000000000..eb5aeca59e
--- /dev/null
+++ b/REORG.TODO/elf/restest1.c
@@ -0,0 +1,57 @@
+#include <dlfcn.h>
+#include <error.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  int (*fp1) (int);
+  void *h2;
+  int (*fp2) (int);
+  int res1;
+  int res2;
+
+  mtrace ();
+
+  h1 = dlopen ("testobj1.so", RTLD_LAZY);
+  if (h1 == NULL)
+    error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
+	   dlerror ());
+
+  h2 = dlopen ("testobj1_1.so", RTLD_LAZY);
+  if (h1 == NULL)
+    error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1_1.so",
+	   dlerror ());
+
+  fp1 = dlsym (h1, "obj1func1");
+  if (fp1 == NULL)
+    error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s",
+	   "testobj1.so", dlerror ());
+
+  fp2 = dlsym (h2, "obj1func1");
+  if (fp2 == NULL)
+    error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s",
+	   "testobj1_1.so", dlerror ());
+
+  res1 = fp1 (10);
+  res2 = fp2 (10);
+  printf ("fp1(10) = %d\nfp2(10) = %d\n", res1, res2);
+
+  if (dlclose (h1) != 0)
+    error (EXIT_FAILURE, 0, "cannot close testobj1.so: %s\n", dlerror ());
+  if (dlclose (h2) != 0)
+    error (EXIT_FAILURE, 0, "cannot close testobj1_1.so: %s\n", dlerror ());
+
+  return res1 != 42 || res2 != 72;
+}
+
+
+extern int foo (int a);
+int
+foo (int a)
+{
+  return a + 10;
+}
diff --git a/REORG.TODO/elf/restest2.c b/REORG.TODO/elf/restest2.c
new file mode 100644
index 0000000000..f959f030a0
--- /dev/null
+++ b/REORG.TODO/elf/restest2.c
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <dlfcn.h>
+#include <error.h>
+#include <mcheck.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pid_t pid, pid2;
+
+pid_t getpid(void)
+{
+  pid_t (*f)(void);
+  f = (pid_t (*)(void)) dlsym (RTLD_NEXT, "getpid");
+  if (f == NULL)
+    error (EXIT_FAILURE, 0, "dlsym (RTLD_NEXT, \"getpid\"): %s", dlerror ());
+  return (pid2 = f()) + 26;
+}
+
+int
+main (void)
+{
+  pid_t (*f)(void);
+
+  mtrace ();
+
+  f = (pid_t (*)(void)) dlsym (RTLD_DEFAULT, "getpid");
+  if (f == NULL)
+    error (EXIT_FAILURE, 0, "dlsym (RTLD_DEFAULT, \"getpid\"): %s", dlerror ());
+  pid = f();
+  if (pid != pid2 + 26)
+    error (EXIT_FAILURE, 0, "main getpid() not called");
+  return 0;
+}
diff --git a/REORG.TODO/elf/rtld-Rules b/REORG.TODO/elf/rtld-Rules
new file mode 100644
index 0000000000..2c7b99828c
--- /dev/null
+++ b/REORG.TODO/elf/rtld-Rules
@@ -0,0 +1,149 @@
+# Subroutine makefile for compiling libc modules linked into dynamic linker.
+
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# This makefile is never used by itself, but only from the rtld-libc.a
+# rule in Makefile, which does make -f librtld.mk -f rtld-Rules.
+# librtld.mk is the generated file containing variable definitions for
+# `rtld-subdirs', a subset of the top-level $(subdirs) list; and for each
+# SUBDIR in $(rtld-subdirs), `rtld-SUBDIR' listing `module.os' file names.
+
+.PHONY: rtld-all
+rtld-all:
+
+# When run from the elf/Makefile to build rtld-libc.a, $(subdir) is elf.
+ifneq ($(subdir),elf)
+ifndef rtld-modules
+error rtld-modules not set
+endif
+endif
+
+ifndef rtld-modules
+# Running to build rtld-libc.a, driving runs of $(rtld-subdir-make), below.
+
+ifndef rtld-subdirs
+error This makefile is a subroutine of elf/Makefile not to be used directly
+endif
+
+include ../Makeconfig
+
+rtld-all: $(objpfx)rtld-libc.a
+
+$(objpfx)rtld-libc.a: $(foreach dir,$(rtld-subdirs),\
+				$(addprefix $(common-objpfx)$(dir)/rtld-,\
+					    $(rtld-$(dir))))
+	@-rm -f $@T
+	$(AR) cq$(verbose) $@T $^
+	mv -f $@T $@
+
+# Use the verbose option of ar and tar when not running silently.
+ifeq	"$(findstring s,$(MAKEFLAGS))" ""	# if not -s
+verbose := v
+else						# -s
+verbose	:=
+endif						# not -s
+
+
+# For each subdirectory, define a pattern rule that makes all of that
+# subdirectory's modules at once with one recursive make command.
+object-suffixes-left := $(rtld-subdirs)
+define o-iterator-doit
+$(foreach obj,$(rtld-$o),$(common-objpfx)%/rtld-$(obj)): FORCE ; \
+	+$$(rtld-subdir-make)
+endef
+include $(patsubst %,../o-iterator.mk,$(object-suffixes-left))
+
+# This is how we descend into each subdirectory.  See below.
+define rtld-subdir-make
+$(MAKE) $(subdir-args) objdir=$(objdir) \
+	-f Makefile -f ../elf/rtld-Rules rtld-all \
+	rtld-modules='$(addprefix rtld-,$(rtld-$*))'
+endef
+
+# See subdir-target-args in ../Makefile for the model.
+subdir-args = subdir=$*$(if $($*-srcdir),\
+			    -C $($*-srcdir) ..=`pwd`/,\
+			    -C $(..)$* ..=../)
+
+FORCE:
+
+else
+
+# In this case we are being run by $(rtld-subdir-make), above.
+# Some other subdir's Makefile has provided all its normal rules,
+# and we just provide some additional definitions.
+
+rtld-compile-command.S = $(compile-command.S) $(rtld-CPPFLAGS)
+rtld-compile-command.s = $(compile-command.s) $(rtld-CPPFLAGS)
+rtld-compile-command.c = $(compile-command.c) $(rtld-CPPFLAGS) $(rtld-CFLAGS)
+
+# These are the basic compilation rules corresponding to the Makerules ones.
+# The sysd-rules generated makefile already defines pattern rules for rtld-%
+# targets built from sysdeps source files.
+$(objpfx)rtld-%.os: rtld-%.S $(before-compile)
+	$(rtld-compile-command.S)
+$(objpfx)rtld-%.os: rtld-%.s $(before-compile)
+	$(rtld-compile-command.s)
+$(objpfx)rtld-%.os: rtld-%.c $(before-compile)
+	$(rtld-compile-command.c)
+$(objpfx)rtld-%.os: %.S $(before-compile)
+	$(rtld-compile-command.S)
+$(objpfx)rtld-%.os: %.s $(before-compile)
+	$(rtld-compile-command.s)
+$(objpfx)rtld-%.os: %.c $(before-compile)
+	$(rtld-compile-command.c)
+
+# The rules for generated source files.
+$(objpfx)rtld-%.os: $(objpfx)rtld-%.S $(before-compile)
+	$(rtld-compile-command.S)
+$(objpfx)rtld-%.os: $(objpfx)rtld-%.s $(before-compile)
+	$(rtld-compile-command.s)
+$(objpfx)rtld-%.os: $(objpfx)rtld-%.c $(before-compile)
+	$(rtld-compile-command.c)
+$(objpfx)rtld-%.os: $(objpfx)%.S $(before-compile)
+	$(rtld-compile-command.S)
+$(objpfx)rtld-%.os: $(objpfx)%.s $(before-compile)
+	$(rtld-compile-command.s)
+$(objpfx)rtld-%.os: $(objpfx)%.c $(before-compile)
+	$(rtld-compile-command.c)
+
+# The command line setting of rtld-modules (see above) tells us
+# what we need to build, and that tells us what dependency files we need.
+rtld-all: $(addprefix $(objpfx),$(rtld-modules))
+
+# Figure out the dependency files we need.  After respecting the $(omit-deps)
+# list as applied to the names without the `rtld-', there may be none left.
+rtld-depfiles := $(patsubst %,$(objpfx)rtld-%.os.d,\
+			    $(filter-out $(omit-deps),\
+					 $(rtld-modules:rtld-%.os=%)))
+rtld-depfiles := $(strip $(wildcard $(rtld-depfiles)) \
+			 $(patsubst %.dt,%.d,\
+				    $(wildcard $(rtld-depfiles:.d=.dt))))
+ifdef rtld-depfiles
+-include $(rtld-depfiles)
+endif
+
+# This here is the whole point of all the shenanigans.
+# Set libof-* for each routine.
+cpp-srcs-left := $(rtld-modules:%.os=%)
+lib := rtld
+include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
+
+rtld-CFLAGS += $(no-stack-protector)
+
+endif
diff --git a/REORG.TODO/elf/rtld-debugger-interface.txt b/REORG.TODO/elf/rtld-debugger-interface.txt
new file mode 100644
index 0000000000..61bc99e4b0
--- /dev/null
+++ b/REORG.TODO/elf/rtld-debugger-interface.txt
@@ -0,0 +1,122 @@
+Standard debugger interface
+===========================
+
+The run-time linker exposes a rendezvous structure to allow debuggers
+to interface with it.  This structure, r_debug, is defined in link.h.
+If the executable's dynamic section has a DT_DEBUG element, the
+run-time linker sets that element's value to the address where this
+structure can be found.
+
+The r_debug structure contains (amongst others) the following fields:
+
+  struct link_map *r_map:
+    A linked list of loaded objects.
+
+  enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state:
+    The current state of the r_map list.  RT_CONSISTENT means that r_map
+    is not currently being modified and may safely be inspected.  RT_ADD
+    means that an object is being added to r_map, and that the list is
+    not guaranteed to be consistent.  Likewise RT_DELETE means that an
+    object is being removed from the list.
+
+  ElfW(Addr) r_brk:
+    The address of a function internal to the run-time linker which is
+    called whenever r_state is changed.  The debugger should set a
+    breakpoint at this address if it wants to notice mapping changes.
+
+This protocol is widely supported, but somewhat limited in that it
+has no provision to provide access to multiple namespaces, and that
+the notifications (via r_brk) only refer to changes to r_map--the
+debugger is notified that a new object has been added, for instance,
+but there is no way for the debugger to discover whether any of the
+objects in the link-map have been relocated or not.
+
+
+Probe-based debugger interface
+==============================
+
+Systemtap is a dynamic tracing/instrumenting tool available on Linux.
+Probes that are not fired at run time have close to zero overhead.
+glibc contains a number of probes that debuggers can set breakpoints
+on in order to notice certain events.
+
+All rtld probes have the following arguments:
+
+  arg1: Lmid_t lmid:
+    The link-map ID of the link-map list that the object was loaded
+    into.  This will be LM_ID_BASE for the application's main link-map
+    list, or some other value for different namespaces.
+
+  arg2: struct r_debug *r_debug:
+    A pointer to the r_debug structure containing the link-map list
+    that the object was loaded into.  This will be the value stored in
+    DT_DEBUG for the application's main link-map list, or some other
+    value for different namespaces.
+
+map_complete and reloc_complete may have the following additional
+argument:
+
+  arg3: struct link_map *new:
+    A pointer which, if not NULL, points to the entry in the specified
+    r_debug structure's link-map list corresponding to the first new
+    object to have been mapped or relocated, with new->l_next pointing
+    to the link-map of the next new object to have been mapped or
+    relocated, and so on.  Note that because `new' is an entry in a
+    larger list, new->l_prev (if not NULL) will point to what was the
+    last link-map in the link-map list prior to the new objects being
+    mapped or relocated.
+
+The following probes are available:
+
+  init_start:
+    This is called once, when the linker is about to fill in the main
+    r_debug structure at application startup.  init_start always has
+    lmid set to LM_ID_BASE and r_debug set to the value stored in
+    DT_DEBUG.  r_debug is not guaranteed to be consistent until
+    init_complete is fired.
+
+  init_complete:
+    This is called once, when the linker has filled in the main
+    r_debug structure at application startup. init_complete always
+    has lmid set to LM_ID_BASE and r_debug set to the value stored
+    in DT_DEBUG.  The r_debug structure is consistent and may be
+    inspected, and all objects in the link-map are guaranteed to
+    have been relocated.
+
+  map_start:
+    The linker is about to map new objects into the specified
+    namespace.  The namespace's r_debug structure is not guaranteed
+    to be consistent until a corresponding map_complete is fired.
+
+  map_complete:
+    The linker has finished mapping new objects into the specified
+    namespace.  The namespace's r_debug structure is consistent and
+    may be inspected, although objects in the namespace's link-map
+    are not guaranteed to have been relocated.
+
+  map_failed:
+    The linker failed while attempting to map new objects into
+    the specified namespace.  The namespace's r_debug structure
+    is consistent and may be inspected.
+
+  reloc_start:
+    The linker is about to relocate all unrelocated objects in the
+    specified namespace.  The namespace's r_debug structure is not
+    guaranteed to be consistent until a corresponding reloc_complete
+    is fired.
+
+  reloc_complete:
+    The linker has relocated all objects in the specified namespace.
+    The namespace's r_debug structure is consistent and may be
+    inspected, and all objects in the namespace's link-map are
+    guaranteed to have been relocated.
+
+  unmap_start:
+    The linker is about to remove objects from the specified
+    namespace.  The namespace's r_debug structure is not guaranteed to
+    be consistent until a corresponding unmap_complete is fired.
+
+  unmap_complete:
+    The linker has finished removing objects into the specified
+    namespace.  The namespace's r_debug structure is consistent and
+    may be inspected.
diff --git a/REORG.TODO/elf/rtld.c b/REORG.TODO/elf/rtld.c
new file mode 100644
index 0000000000..3746653afb
--- /dev/null
+++ b/REORG.TODO/elf/rtld.c
@@ -0,0 +1,2652 @@
+/* Run time dynamic linker.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ldsodefs.h>
+#include <_itoa.h>
+#include <entry.h>
+#include <fpu_control.h>
+#include <hp-timing.h>
+#include <libc-lock.h>
+#include "dynamic-link.h"
+#include <dl-librecon.h>
+#include <unsecvars.h>
+#include <dl-cache.h>
+#include <dl-osinfo.h>
+#include <dl-procinfo.h>
+#include <tls.h>
+#include <stap-probe.h>
+#include <stackinfo.h>
+
+#include <assert.h>
+
+/* Avoid PLT use for our local calls at startup.  */
+extern __typeof (__mempcpy) __mempcpy attribute_hidden;
+
+/* GCC has mental blocks about _exit.  */
+extern __typeof (_exit) exit_internal asm ("_exit") attribute_hidden;
+#define _exit exit_internal
+
+/* Helper function to handle errors while resolving symbols.  */
+static void print_unresolved (int errcode, const char *objname,
+			      const char *errsting);
+
+/* Helper function to handle errors when a version is missing.  */
+static void print_missing_version (int errcode, const char *objname,
+				   const char *errsting);
+
+/* Print the various times we collected.  */
+static void print_statistics (hp_timing_t *total_timep);
+
+/* Add audit objects.  */
+static void process_dl_audit (char *str);
+
+/* This is a list of all the modes the dynamic loader can be in.  */
+enum mode { normal, list, verify, trace };
+
+/* Process all environments variables the dynamic linker must recognize.
+   Since all of them start with `LD_' we are a bit smarter while finding
+   all the entries.  */
+static void process_envvars (enum mode *modep);
+
+#ifdef DL_ARGV_NOT_RELRO
+int _dl_argc attribute_hidden;
+char **_dl_argv = NULL;
+/* Nonzero if we were run directly.  */
+unsigned int _dl_skip_args attribute_hidden;
+#else
+int _dl_argc attribute_relro attribute_hidden;
+char **_dl_argv attribute_relro = NULL;
+unsigned int _dl_skip_args attribute_relro attribute_hidden;
+#endif
+rtld_hidden_data_def (_dl_argv)
+
+#ifndef THREAD_SET_STACK_GUARD
+/* Only exported for architectures that don't store the stack guard canary
+   in thread local area.  */
+uintptr_t __stack_chk_guard attribute_relro;
+#endif
+
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+     attribute_relro attribute_hidden __attribute__ ((nocommon));
+#ifndef THREAD_SET_POINTER_GUARD
+strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
+#endif
+
+
+/* List of auditing DSOs.  */
+static struct audit_list
+{
+  const char *name;
+  struct audit_list *next;
+} *audit_list;
+
+#ifndef HAVE_INLINED_SYSCALLS
+/* Set nonzero during loading and initialization of executable and
+   libraries, cleared before the executable's entry point runs.  This
+   must not be initialized to nonzero, because the unused dynamic
+   linker loaded in for libc.so's "ld.so.1" dep will provide the
+   definition seen by libc.so's initializer; that value must be zero,
+   and will be since that dynamic linker's _dl_start and dl_main will
+   never be called.  */
+int _dl_starting_up = 0;
+rtld_hidden_def (_dl_starting_up)
+#endif
+
+/* This is the structure which defines all variables global to ld.so
+   (except those which cannot be added for some reason).  */
+struct rtld_global _rtld_global =
+  {
+    /* Generally the default presumption without further information is an
+     * executable stack but this is not true for all platforms.  */
+    ._dl_stack_flags = DEFAULT_STACK_PERMS,
+#ifdef _LIBC_REENTRANT
+    ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
+    ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
+#endif
+    ._dl_nns = 1,
+    ._dl_ns =
+    {
+#ifdef _LIBC_REENTRANT
+      [LM_ID_BASE] = { ._ns_unique_sym_table
+		       = { .lock = _RTLD_LOCK_RECURSIVE_INITIALIZER } }
+#endif
+    }
+  };
+/* If we would use strong_alias here the compiler would see a
+   non-hidden definition.  This would undo the effect of the previous
+   declaration.  So spell out was strong_alias does plus add the
+   visibility attribute.  */
+extern struct rtld_global _rtld_local
+    __attribute__ ((alias ("_rtld_global"), visibility ("hidden")));
+
+
+/* This variable is similar to _rtld_local, but all values are
+   read-only after relocation.  */
+struct rtld_global_ro _rtld_global_ro attribute_relro =
+  {
+    /* Get architecture specific initializer.  */
+#include <dl-procinfo.c>
+#ifdef NEED_DL_SYSINFO
+    ._dl_sysinfo = DL_SYSINFO_DEFAULT,
+#endif
+    ._dl_debug_fd = STDERR_FILENO,
+    ._dl_use_load_bias = -2,
+    ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID,
+#if !HAVE_TUNABLES
+    ._dl_hwcap_mask = HWCAP_IMPORTANT,
+#endif
+    ._dl_lazy = 1,
+    ._dl_fpu_control = _FPU_DEFAULT,
+    ._dl_pagesize = EXEC_PAGESIZE,
+    ._dl_inhibit_cache = 0,
+
+    /* Function pointers.  */
+    ._dl_debug_printf = _dl_debug_printf,
+    ._dl_mcount = _dl_mcount,
+    ._dl_lookup_symbol_x = _dl_lookup_symbol_x,
+    ._dl_check_caller = _dl_check_caller,
+    ._dl_open = _dl_open,
+    ._dl_close = _dl_close,
+    ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
+#ifdef HAVE_DL_DISCOVER_OSVERSION
+    ._dl_discover_osversion = _dl_discover_osversion
+#endif
+  };
+/* If we would use strong_alias here the compiler would see a
+   non-hidden definition.  This would undo the effect of the previous
+   declaration.  So spell out was strong_alias does plus add the
+   visibility attribute.  */
+extern struct rtld_global_ro _rtld_local_ro
+    __attribute__ ((alias ("_rtld_global_ro"), visibility ("hidden")));
+
+
+static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
+		     ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv);
+
+/* These two variables cannot be moved into .data.rel.ro.  */
+static struct libname_list _dl_rtld_libname;
+static struct libname_list _dl_rtld_libname2;
+
+/* Variable for statistics.  */
+#ifndef HP_TIMING_NONAVAIL
+static hp_timing_t relocate_time;
+static hp_timing_t load_time attribute_relro;
+static hp_timing_t start_time attribute_relro;
+#endif
+
+/* Additional definitions needed by TLS initialization.  */
+#ifdef TLS_INIT_HELPER
+TLS_INIT_HELPER
+#endif
+
+/* Helper function for syscall implementation.  */
+#ifdef DL_SYSINFO_IMPLEMENTATION
+DL_SYSINFO_IMPLEMENTATION
+#endif
+
+/* Before ld.so is relocated we must not access variables which need
+   relocations.  This means variables which are exported.  Variables
+   declared as static are fine.  If we can mark a variable hidden this
+   is fine, too.  The latter is important here.  We can avoid setting
+   up a temporary link map for ld.so if we can mark _rtld_global as
+   hidden.  */
+#ifdef PI_STATIC_AND_HIDDEN
+# define DONT_USE_BOOTSTRAP_MAP	1
+#endif
+
+#ifdef DONT_USE_BOOTSTRAP_MAP
+static ElfW(Addr) _dl_start_final (void *arg);
+#else
+struct dl_start_final_info
+{
+  struct link_map l;
+#if !defined HP_TIMING_NONAVAIL && HP_TIMING_INLINE
+  hp_timing_t start_time;
+#endif
+};
+static ElfW(Addr) _dl_start_final (void *arg,
+				   struct dl_start_final_info *info);
+#endif
+
+/* These defined magically in the linker script.  */
+extern char _begin[] attribute_hidden;
+extern char _etext[] attribute_hidden;
+extern char _end[] attribute_hidden;
+
+
+#ifdef RTLD_START
+RTLD_START
+#else
+# error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START"
+#endif
+
+/* This is the second half of _dl_start (below).  It can be inlined safely
+   under DONT_USE_BOOTSTRAP_MAP, where it is careful not to make any GOT
+   references.  When the tools don't permit us to avoid using a GOT entry
+   for _dl_rtld_global (no attribute_hidden support), we must make sure
+   this function is not inlined (see below).  */
+
+#ifdef DONT_USE_BOOTSTRAP_MAP
+static inline ElfW(Addr) __attribute__ ((always_inline))
+_dl_start_final (void *arg)
+#else
+static ElfW(Addr) __attribute__ ((noinline))
+_dl_start_final (void *arg, struct dl_start_final_info *info)
+#endif
+{
+  ElfW(Addr) start_addr;
+
+  if (HP_SMALL_TIMING_AVAIL)
+    {
+      /* If it hasn't happen yet record the startup time.  */
+      if (! HP_TIMING_INLINE)
+	HP_TIMING_NOW (start_time);
+#if !defined DONT_USE_BOOTSTRAP_MAP && !defined HP_TIMING_NONAVAIL
+      else
+	start_time = info->start_time;
+#endif
+    }
+
+  /* Transfer data about ourselves to the permanent link_map structure.  */
+#ifndef DONT_USE_BOOTSTRAP_MAP
+  GL(dl_rtld_map).l_addr = info->l.l_addr;
+  GL(dl_rtld_map).l_ld = info->l.l_ld;
+  memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
+	  sizeof GL(dl_rtld_map).l_info);
+  GL(dl_rtld_map).l_mach = info->l.l_mach;
+  GL(dl_rtld_map).l_relocated = 1;
+#endif
+  _dl_setup_hash (&GL(dl_rtld_map));
+  GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
+  GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
+  GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
+  GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
+  /* Copy the TLS related data if necessary.  */
+#ifndef DONT_USE_BOOTSTRAP_MAP
+# if NO_TLS_OFFSET != 0
+  GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET;
+# endif
+#endif
+
+  HP_TIMING_NOW (GL(dl_cpuclock_offset));
+
+  /* Initialize the stack end variable.  */
+  __libc_stack_end = __builtin_frame_address (0);
+
+  /* Call the OS-dependent function to set up life so we can do things like
+     file access.  It will call `dl_main' (below) to do all the real work
+     of the dynamic linker, and then unwind our frame and run the user
+     entry point on the same stack we entered on.  */
+  start_addr = _dl_sysdep_start (arg, &dl_main);
+
+#ifndef HP_TIMING_NONAVAIL
+  hp_timing_t rtld_total_time;
+  if (HP_SMALL_TIMING_AVAIL)
+    {
+      hp_timing_t end_time;
+
+      /* Get the current time.  */
+      HP_TIMING_NOW (end_time);
+
+      /* Compute the difference.  */
+      HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
+    }
+#endif
+
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
+    {
+#ifndef HP_TIMING_NONAVAIL
+      print_statistics (&rtld_total_time);
+#else
+      print_statistics (NULL);
+#endif
+    }
+
+  return start_addr;
+}
+
+static ElfW(Addr) __attribute_used__ internal_function
+_dl_start (void *arg)
+{
+#ifdef DONT_USE_BOOTSTRAP_MAP
+# define bootstrap_map GL(dl_rtld_map)
+#else
+  struct dl_start_final_info info;
+# define bootstrap_map info.l
+#endif
+
+  /* This #define produces dynamic linking inline functions for
+     bootstrap relocation instead of general-purpose relocation.
+     Since ld.so must not have any undefined symbols the result
+     is trivial: always the map of ld.so itself.  */
+#define RTLD_BOOTSTRAP
+#define RESOLVE_MAP(sym, version, flags) (&bootstrap_map)
+#include "dynamic-link.h"
+
+  if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL)
+#ifdef DONT_USE_BOOTSTRAP_MAP
+    HP_TIMING_NOW (start_time);
+#else
+    HP_TIMING_NOW (info.start_time);
+#endif
+
+  /* Partly clean the `bootstrap_map' structure up.  Don't use
+     `memset' since it might not be built in or inlined and we cannot
+     make function calls at this point.  Use '__builtin_memset' if we
+     know it is available.  We do not have to clear the memory if we
+     do not have to use the temporary bootstrap_map.  Global variables
+     are initialized to zero by default.  */
+#ifndef DONT_USE_BOOTSTRAP_MAP
+# ifdef HAVE_BUILTIN_MEMSET
+  __builtin_memset (bootstrap_map.l_info, '\0', sizeof (bootstrap_map.l_info));
+# else
+  for (size_t cnt = 0;
+       cnt < sizeof (bootstrap_map.l_info) / sizeof (bootstrap_map.l_info[0]);
+       ++cnt)
+    bootstrap_map.l_info[cnt] = 0;
+# endif
+#endif
+
+  /* Figure out the run-time load address of the dynamic linker itself.  */
+  bootstrap_map.l_addr = elf_machine_load_address ();
+
+  /* Read our own dynamic section and fill in the info array.  */
+  bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
+  elf_get_dynamic_info (&bootstrap_map, NULL);
+
+#if NO_TLS_OFFSET != 0
+  bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
+#endif
+
+#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
+#endif
+
+  if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
+    {
+      /* Relocate ourselves so we can do normal function calls and
+	 data access using the global offset table.  */
+
+      ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
+    }
+  bootstrap_map.l_relocated = 1;
+
+  /* Please note that we don't allow profiling of this object and
+     therefore need not test whether we have to allocate the array
+     for the relocation results (as done in dl-reloc.c).  */
+
+  /* Now life is sane; we can call functions and access global data.
+     Set up to use the operating system facilities, and find out from
+     the operating system's program loader where to find the program
+     header table in core.  Put the rest of _dl_start into a separate
+     function, that way the compiler cannot put accesses to the GOT
+     before ELF_DYNAMIC_RELOCATE.  */
+  {
+#ifdef DONT_USE_BOOTSTRAP_MAP
+    ElfW(Addr) entry = _dl_start_final (arg);
+#else
+    ElfW(Addr) entry = _dl_start_final (arg, &info);
+#endif
+
+#ifndef ELF_MACHINE_START_ADDRESS
+# define ELF_MACHINE_START_ADDRESS(map, start) (start)
+#endif
+
+    return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
+  }
+}
+
+
+
+/* Now life is peachy; we can do all normal operations.
+   On to the real work.  */
+
+/* Some helper functions.  */
+
+/* Arguments to relocate_doit.  */
+struct relocate_args
+{
+  struct link_map *l;
+  int reloc_mode;
+};
+
+struct map_args
+{
+  /* Argument to map_doit.  */
+  const char *str;
+  struct link_map *loader;
+  int mode;
+  /* Return value of map_doit.  */
+  struct link_map *map;
+};
+
+struct dlmopen_args
+{
+  const char *fname;
+  struct link_map *map;
+};
+
+struct lookup_args
+{
+  const char *name;
+  struct link_map *map;
+  void *result;
+};
+
+/* Arguments to version_check_doit.  */
+struct version_check_args
+{
+  int doexit;
+  int dotrace;
+};
+
+static void
+relocate_doit (void *a)
+{
+  struct relocate_args *args = (struct relocate_args *) a;
+
+  _dl_relocate_object (args->l, args->l->l_scope, args->reloc_mode, 0);
+}
+
+static void
+map_doit (void *a)
+{
+  struct map_args *args = (struct map_args *) a;
+  int type = (args->mode == __RTLD_OPENEXEC) ? lt_executable : lt_library;
+  args->map = _dl_map_object (args->loader, args->str, type, 0,
+			      args->mode, LM_ID_BASE);
+}
+
+static void
+dlmopen_doit (void *a)
+{
+  struct dlmopen_args *args = (struct dlmopen_args *) a;
+  args->map = _dl_open (args->fname,
+			(RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT
+			 | __RTLD_SECURE),
+			dl_main, LM_ID_NEWLM, _dl_argc, _dl_argv,
+			__environ);
+}
+
+static void
+lookup_doit (void *a)
+{
+  struct lookup_args *args = (struct lookup_args *) a;
+  const ElfW(Sym) *ref = NULL;
+  args->result = NULL;
+  lookup_t l = _dl_lookup_symbol_x (args->name, args->map, &ref,
+				    args->map->l_local_scope, NULL, 0,
+				    DL_LOOKUP_RETURN_NEWEST, NULL);
+  if (ref != NULL)
+    args->result = DL_SYMBOL_ADDRESS (l, ref);
+}
+
+static void
+version_check_doit (void *a)
+{
+  struct version_check_args *args = (struct version_check_args *) a;
+  if (_dl_check_all_versions (GL(dl_ns)[LM_ID_BASE]._ns_loaded, 1,
+			      args->dotrace) && args->doexit)
+    /* We cannot start the application.  Abort now.  */
+    _exit (1);
+}
+
+
+static inline struct link_map *
+find_needed (const char *name)
+{
+  struct r_scope_elem *scope = &GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_searchlist;
+  unsigned int n = scope->r_nlist;
+
+  while (n-- > 0)
+    if (_dl_name_match_p (name, scope->r_list[n]))
+      return scope->r_list[n];
+
+  /* Should never happen.  */
+  return NULL;
+}
+
+static int
+match_version (const char *string, struct link_map *map)
+{
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+  ElfW(Verdef) *def;
+
+#define VERDEFTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERDEF))
+  if (map->l_info[VERDEFTAG] == NULL)
+    /* The file has no symbol versioning.  */
+    return 0;
+
+  def = (ElfW(Verdef) *) ((char *) map->l_addr
+			  + map->l_info[VERDEFTAG]->d_un.d_ptr);
+  while (1)
+    {
+      ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);
+
+      /* Compare the version strings.  */
+      if (strcmp (string, strtab + aux->vda_name) == 0)
+	/* Bingo!  */
+	return 1;
+
+      /* If no more definitions we failed to find what we want.  */
+      if (def->vd_next == 0)
+	break;
+
+      /* Next definition.  */
+      def = (ElfW(Verdef) *) ((char *) def + def->vd_next);
+    }
+
+  return 0;
+}
+
+static bool tls_init_tp_called;
+
+static void *
+init_tls (void)
+{
+  /* Number of elements in the static TLS block.  */
+  GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+
+  /* Do not do this twice.  The audit interface might have required
+     the DTV interfaces to be set up early.  */
+  if (GL(dl_initial_dtv) != NULL)
+    return NULL;
+
+  /* Allocate the array which contains the information about the
+     dtv slots.  We allocate a few entries more than needed to
+     avoid the need for reallocation.  */
+  size_t nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS;
+
+  /* Allocate.  */
+  GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *)
+    calloc (sizeof (struct dtv_slotinfo_list)
+	    + nelem * sizeof (struct dtv_slotinfo), 1);
+  /* No need to check the return value.  If memory allocation failed
+     the program would have been terminated.  */
+
+  struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+  GL(dl_tls_dtv_slotinfo_list)->len = nelem;
+  GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+
+  /* Fill in the information from the loaded modules.  No namespace
+     but the base one can be filled at this time.  */
+  assert (GL(dl_ns)[LM_ID_BASE + 1]._ns_loaded == NULL);
+  int i = 0;
+  for (struct link_map *l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL;
+       l = l->l_next)
+    if (l->l_tls_blocksize != 0)
+      {
+	/* This is a module with TLS data.  Store the map reference.
+	   The generation counter is zero.  */
+	slotinfo[i].map = l;
+	/* slotinfo[i].gen = 0; */
+	++i;
+      }
+  assert (i == GL(dl_tls_max_dtv_idx));
+
+  /* Compute the TLS offsets for the various blocks.  */
+  _dl_determine_tlsoffset ();
+
+  /* Construct the static TLS block and the dtv for the initial
+     thread.  For some platforms this will include allocating memory
+     for the thread descriptor.  The memory for the TLS block will
+     never be freed.  It should be allocated accordingly.  The dtv
+     array can be changed if dynamic loading requires it.  */
+  void *tcbp = _dl_allocate_tls_storage ();
+  if (tcbp == NULL)
+    _dl_fatal_printf ("\
+cannot allocate TLS data structures for initial thread");
+
+  /* Store for detection of the special case by __tls_get_addr
+     so it knows not to pass this dtv to the normal realloc.  */
+  GL(dl_initial_dtv) = GET_DTV (tcbp);
+
+  /* And finally install it for the main thread.  */
+  const char *lossage = TLS_INIT_TP (tcbp);
+  if (__glibc_unlikely (lossage != NULL))
+    _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+  tls_init_tp_called = true;
+
+  return tcbp;
+}
+
+static unsigned int
+do_preload (const char *fname, struct link_map *main_map, const char *where)
+{
+  const char *objname;
+  const char *err_str = NULL;
+  struct map_args args;
+  bool malloced;
+
+  args.str = fname;
+  args.loader = main_map;
+  args.mode = __RTLD_SECURE;
+
+  unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+
+  (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args);
+  if (__glibc_unlikely (err_str != NULL))
+    {
+      _dl_error_printf ("\
+ERROR: ld.so: object '%s' from %s cannot be preloaded (%s): ignored.\n",
+			fname, where, err_str);
+      /* No need to call free, this is still before
+	 the libc's malloc is used.  */
+    }
+  else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded)
+    /* It is no duplicate.  */
+    return 1;
+
+  /* Nothing loaded.  */
+  return 0;
+}
+
+#if defined SHARED && defined _LIBC_REENTRANT \
+    && defined __rtld_lock_default_lock_recursive
+static void
+rtld_lock_default_lock_recursive (void *lock)
+{
+  __rtld_lock_default_lock_recursive (lock);
+}
+
+static void
+rtld_lock_default_unlock_recursive (void *lock)
+{
+  __rtld_lock_default_unlock_recursive (lock);
+}
+#endif
+
+
+static void
+security_init (void)
+{
+  /* Set up the stack checker's canary.  */
+  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
+#ifdef THREAD_SET_STACK_GUARD
+  THREAD_SET_STACK_GUARD (stack_chk_guard);
+#else
+  __stack_chk_guard = stack_chk_guard;
+#endif
+
+  /* Set up the pointer guard as well, if necessary.  */
+  uintptr_t pointer_chk_guard
+    = _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
+#ifdef THREAD_SET_POINTER_GUARD
+  THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+#endif
+  __pointer_chk_guard_local = pointer_chk_guard;
+
+  /* We do not need the _dl_random value anymore.  The less
+     information we leave behind, the better, so clear the
+     variable.  */
+  _dl_random = NULL;
+}
+
+#include "setup-vdso.h"
+
+/* The library search path.  */
+static const char *library_path attribute_relro;
+/* The list preloaded objects.  */
+static const char *preloadlist attribute_relro;
+/* Nonzero if information about versions has to be printed.  */
+static int version_info attribute_relro;
+
+static void
+dl_main (const ElfW(Phdr) *phdr,
+	 ElfW(Word) phnum,
+	 ElfW(Addr) *user_entry,
+	 ElfW(auxv_t) *auxv)
+{
+  const ElfW(Phdr) *ph;
+  enum mode mode;
+  struct link_map *main_map;
+  size_t file_size;
+  char *file;
+  bool has_interp = false;
+  unsigned int i;
+  bool prelinked = false;
+  bool rtld_is_main = false;
+#ifndef HP_TIMING_NONAVAIL
+  hp_timing_t start;
+  hp_timing_t stop;
+  hp_timing_t diff;
+#endif
+  void *tcbp = NULL;
+
+  GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
+
+#if defined SHARED && defined _LIBC_REENTRANT \
+    && defined __rtld_lock_default_lock_recursive
+  GL(dl_rtld_lock_recursive) = rtld_lock_default_lock_recursive;
+  GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive;
+#endif
+
+  /* The explicit initialization here is cheaper than processing the reloc
+     in the _rtld_local definition's initializer.  */
+  GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
+
+  /* Process the environment variable which control the behaviour.  */
+  process_envvars (&mode);
+
+#ifndef HAVE_INLINED_SYSCALLS
+  /* Set up a flag which tells we are just starting.  */
+  _dl_starting_up = 1;
+#endif
+
+  if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
+    {
+      /* Ho ho.  We are not the program interpreter!  We are the program
+	 itself!  This means someone ran ld.so as a command.  Well, that
+	 might be convenient to do sometimes.  We support it by
+	 interpreting the args like this:
+
+	 ld.so PROGRAM ARGS...
+
+	 The first argument is the name of a file containing an ELF
+	 executable we will load and run with the following arguments.
+	 To simplify life here, PROGRAM is searched for using the
+	 normal rules for shared objects, rather than $PATH or anything
+	 like that.  We just load it and use its entry point; we don't
+	 pay attention to its PT_INTERP command (we are the interpreter
+	 ourselves).  This is an easy way to test a new ld.so before
+	 installing it.  */
+      rtld_is_main = true;
+
+      /* Note the place where the dynamic linker actually came from.  */
+      GL(dl_rtld_map).l_name = rtld_progname;
+
+      while (_dl_argc > 1)
+	if (! strcmp (_dl_argv[1], "--list"))
+	  {
+	    mode = list;
+	    GLRO(dl_lazy) = -1;	/* This means do no dependency analysis.  */
+
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--verify"))
+	  {
+	    mode = verify;
+
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--inhibit-cache"))
+	  {
+	    GLRO(dl_inhibit_cache) = 1;
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--library-path")
+		 && _dl_argc > 2)
+	  {
+	    library_path = _dl_argv[2];
+
+	    _dl_skip_args += 2;
+	    _dl_argc -= 2;
+	    _dl_argv += 2;
+	  }
+	else if (! strcmp (_dl_argv[1], "--inhibit-rpath")
+		 && _dl_argc > 2)
+	  {
+	    GLRO(dl_inhibit_rpath) = _dl_argv[2];
+
+	    _dl_skip_args += 2;
+	    _dl_argc -= 2;
+	    _dl_argv += 2;
+	  }
+	else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2)
+	  {
+	    process_dl_audit (_dl_argv[2]);
+
+	    _dl_skip_args += 2;
+	    _dl_argc -= 2;
+	    _dl_argv += 2;
+	  }
+	else
+	  break;
+
+      /* If we have no further argument the program was called incorrectly.
+	 Grant the user some education.  */
+      if (_dl_argc < 2)
+	_dl_fatal_printf ("\
+Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
+You have invoked `ld.so', the helper program for shared library executables.\n\
+This program usually lives in the file `/lib/ld.so', and special directives\n\
+in executable files using ELF shared libraries tell the system's program\n\
+loader to load the helper program from this file.  This helper program loads\n\
+the shared libraries needed by the program executable, prepares the program\n\
+to run, and runs it.  You may invoke this helper program directly from the\n\
+command line to load and run an ELF executable file; this is like executing\n\
+that file itself, but always uses this helper program from the file you\n\
+specified, instead of the helper program file specified in the executable\n\
+file you run.  This is mostly of use for maintainers to test new versions\n\
+of this helper program; chances are you did not intend to run this program.\n\
+\n\
+  --list                list all dependencies and how they are resolved\n\
+  --verify              verify that given object really is a dynamically linked\n\
+			object we can handle\n\
+  --inhibit-cache       Do not use " LD_SO_CACHE "\n\
+  --library-path PATH   use given PATH instead of content of the environment\n\
+			variable LD_LIBRARY_PATH\n\
+  --inhibit-rpath LIST  ignore RUNPATH and RPATH information in object names\n\
+			in LIST\n\
+  --audit LIST          use objects named in LIST as auditors\n");
+
+      ++_dl_skip_args;
+      --_dl_argc;
+      ++_dl_argv;
+
+      /* The initialization of _dl_stack_flags done below assumes the
+	 executable's PT_GNU_STACK may have been honored by the kernel, and
+	 so a PT_GNU_STACK with PF_X set means the stack started out with
+	 execute permission.  However, this is not really true if the
+	 dynamic linker is the executable the kernel loaded.  For this
+	 case, we must reinitialize _dl_stack_flags to match the dynamic
+	 linker itself.  If the dynamic linker was built with a
+	 PT_GNU_STACK, then the kernel may have loaded us with a
+	 nonexecutable stack that we will have to make executable when we
+	 load the program below unless it has a PT_GNU_STACK indicating
+	 nonexecutable stack is ok.  */
+
+      for (ph = phdr; ph < &phdr[phnum]; ++ph)
+	if (ph->p_type == PT_GNU_STACK)
+	  {
+	    GL(dl_stack_flags) = ph->p_flags;
+	    break;
+	  }
+
+      if (__builtin_expect (mode, normal) == verify)
+	{
+	  const char *objname;
+	  const char *err_str = NULL;
+	  struct map_args args;
+	  bool malloced;
+
+	  args.str = rtld_progname;
+	  args.loader = NULL;
+	  args.mode = __RTLD_OPENEXEC;
+	  (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit,
+				  &args);
+	  if (__glibc_unlikely (err_str != NULL))
+	    /* We don't free the returned string, the programs stops
+	       anyway.  */
+	    _exit (EXIT_FAILURE);
+	}
+      else
+	{
+	  HP_TIMING_NOW (start);
+	  _dl_map_object (NULL, rtld_progname, lt_executable, 0,
+			  __RTLD_OPENEXEC, LM_ID_BASE);
+	  HP_TIMING_NOW (stop);
+
+	  HP_TIMING_DIFF (load_time, start, stop);
+	}
+
+      /* Now the map for the main executable is available.  */
+      main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+      if (__builtin_expect (mode, normal) == normal
+	  && GL(dl_rtld_map).l_info[DT_SONAME] != NULL
+	  && main_map->l_info[DT_SONAME] != NULL
+	  && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+		     + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val,
+		     (const char *) D_PTR (main_map, l_info[DT_STRTAB])
+		     + main_map->l_info[DT_SONAME]->d_un.d_val) == 0)
+	_dl_fatal_printf ("loader cannot load itself\n");
+
+      phdr = main_map->l_phdr;
+      phnum = main_map->l_phnum;
+      /* We overwrite here a pointer to a malloc()ed string.  But since
+	 the malloc() implementation used at this point is the dummy
+	 implementations which has no real free() function it does not
+	 makes sense to free the old string first.  */
+      main_map->l_name = (char *) "";
+      *user_entry = main_map->l_entry;
+
+#ifdef HAVE_AUX_VECTOR
+      /* Adjust the on-stack auxiliary vector so that it looks like the
+	 binary was executed directly.  */
+      for (ElfW(auxv_t) *av = auxv; av->a_type != AT_NULL; av++)
+	switch (av->a_type)
+	  {
+	  case AT_PHDR:
+	    av->a_un.a_val = (uintptr_t) phdr;
+	    break;
+	  case AT_PHNUM:
+	    av->a_un.a_val = phnum;
+	    break;
+	  case AT_ENTRY:
+	    av->a_un.a_val = *user_entry;
+	    break;
+	  case AT_EXECFN:
+	    av->a_un.a_val = (uintptr_t) _dl_argv[0];
+	    break;
+	  }
+#endif
+    }
+  else
+    {
+      /* Create a link_map for the executable itself.
+	 This will be what dlopen on "" returns.  */
+      main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
+				 __RTLD_OPENEXEC, LM_ID_BASE);
+      assert (main_map != NULL);
+      main_map->l_phdr = phdr;
+      main_map->l_phnum = phnum;
+      main_map->l_entry = *user_entry;
+
+      /* Even though the link map is not yet fully initialized we can add
+	 it to the map list since there are no possible users running yet.  */
+      _dl_add_to_namespace_list (main_map, LM_ID_BASE);
+      assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded);
+
+      /* At this point we are in a bit of trouble.  We would have to
+	 fill in the values for l_dev and l_ino.  But in general we
+	 do not know where the file is.  We also do not handle AT_EXECFD
+	 even if it would be passed up.
+
+	 We leave the values here defined to 0.  This is normally no
+	 problem as the program code itself is normally no shared
+	 object and therefore cannot be loaded dynamically.  Nothing
+	 prevent the use of dynamic binaries and in these situations
+	 we might get problems.  We might not be able to find out
+	 whether the object is already loaded.  But since there is no
+	 easy way out and because the dynamic binary must also not
+	 have an SONAME we ignore this program for now.  If it becomes
+	 a problem we can force people using SONAMEs.  */
+
+      /* We delay initializing the path structure until we got the dynamic
+	 information for the program.  */
+    }
+
+  main_map->l_map_end = 0;
+  main_map->l_text_end = 0;
+  /* Perhaps the executable has no PT_LOAD header entries at all.  */
+  main_map->l_map_start = ~0;
+  /* And it was opened directly.  */
+  ++main_map->l_direct_opencount;
+
+  /* Scan the program header table for the dynamic section.  */
+  for (ph = phdr; ph < &phdr[phnum]; ++ph)
+    switch (ph->p_type)
+      {
+      case PT_PHDR:
+	/* Find out the load address.  */
+	main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;
+	break;
+      case PT_DYNAMIC:
+	/* This tells us where to find the dynamic section,
+	   which tells us everything we need to do.  */
+	main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr;
+	break;
+      case PT_INTERP:
+	/* This "interpreter segment" was used by the program loader to
+	   find the program interpreter, which is this program itself, the
+	   dynamic linker.  We note what name finds us, so that a future
+	   dlopen call or DT_NEEDED entry, for something that wants to link
+	   against the dynamic linker as a shared library, will know that
+	   the shared object is already loaded.  */
+	_dl_rtld_libname.name = ((const char *) main_map->l_addr
+				 + ph->p_vaddr);
+	/* _dl_rtld_libname.next = NULL;	Already zero.  */
+	GL(dl_rtld_map).l_libname = &_dl_rtld_libname;
+
+	/* Ordinarilly, we would get additional names for the loader from
+	   our DT_SONAME.  This can't happen if we were actually linked as
+	   a static executable (detect this case when we have no DYNAMIC).
+	   If so, assume the filename component of the interpreter path to
+	   be our SONAME, and add it to our name list.  */
+	if (GL(dl_rtld_map).l_ld == NULL)
+	  {
+	    const char *p = NULL;
+	    const char *cp = _dl_rtld_libname.name;
+
+	    /* Find the filename part of the path.  */
+	    while (*cp != '\0')
+	      if (*cp++ == '/')
+		p = cp;
+
+	    if (p != NULL)
+	      {
+		_dl_rtld_libname2.name = p;
+		/* _dl_rtld_libname2.next = NULL;  Already zero.  */
+		_dl_rtld_libname.next = &_dl_rtld_libname2;
+	      }
+	  }
+
+	has_interp = true;
+	break;
+      case PT_LOAD:
+	{
+	  ElfW(Addr) mapstart;
+	  ElfW(Addr) allocend;
+
+	  /* Remember where the main program starts in memory.  */
+	  mapstart = (main_map->l_addr
+		      + (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
+	  if (main_map->l_map_start > mapstart)
+	    main_map->l_map_start = mapstart;
+
+	  /* Also where it ends.  */
+	  allocend = main_map->l_addr + ph->p_vaddr + ph->p_memsz;
+	  if (main_map->l_map_end < allocend)
+	    main_map->l_map_end = allocend;
+	  if ((ph->p_flags & PF_X) && allocend > main_map->l_text_end)
+	    main_map->l_text_end = allocend;
+	}
+	break;
+
+      case PT_TLS:
+	if (ph->p_memsz > 0)
+	  {
+	    /* Note that in the case the dynamic linker we duplicate work
+	       here since we read the PT_TLS entry already in
+	       _dl_start_final.  But the result is repeatable so do not
+	       check for this special but unimportant case.  */
+	    main_map->l_tls_blocksize = ph->p_memsz;
+	    main_map->l_tls_align = ph->p_align;
+	    if (ph->p_align == 0)
+	      main_map->l_tls_firstbyte_offset = 0;
+	    else
+	      main_map->l_tls_firstbyte_offset = (ph->p_vaddr
+						  & (ph->p_align - 1));
+	    main_map->l_tls_initimage_size = ph->p_filesz;
+	    main_map->l_tls_initimage = (void *) ph->p_vaddr;
+
+	    /* This image gets the ID one.  */
+	    GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1;
+	  }
+	break;
+
+      case PT_GNU_STACK:
+	GL(dl_stack_flags) = ph->p_flags;
+	break;
+
+      case PT_GNU_RELRO:
+	main_map->l_relro_addr = ph->p_vaddr;
+	main_map->l_relro_size = ph->p_memsz;
+	break;
+      }
+
+  /* Adjust the address of the TLS initialization image in case
+     the executable is actually an ET_DYN object.  */
+  if (main_map->l_tls_initimage != NULL)
+    main_map->l_tls_initimage
+      = (char *) main_map->l_tls_initimage + main_map->l_addr;
+  if (! main_map->l_map_end)
+    main_map->l_map_end = ~0;
+  if (! main_map->l_text_end)
+    main_map->l_text_end = ~0;
+  if (! GL(dl_rtld_map).l_libname && GL(dl_rtld_map).l_name)
+    {
+      /* We were invoked directly, so the program might not have a
+	 PT_INTERP.  */
+      _dl_rtld_libname.name = GL(dl_rtld_map).l_name;
+      /* _dl_rtld_libname.next = NULL;	Already zero.  */
+      GL(dl_rtld_map).l_libname =  &_dl_rtld_libname;
+    }
+  else
+    assert (GL(dl_rtld_map).l_libname); /* How else did we get here?  */
+
+  /* If the current libname is different from the SONAME, add the
+     latter as well.  */
+  if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL
+      && strcmp (GL(dl_rtld_map).l_libname->name,
+		 (const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+		 + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val) != 0)
+    {
+      static struct libname_list newname;
+      newname.name = ((char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+		      + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_ptr);
+      newname.next = NULL;
+      newname.dont_free = 1;
+
+      assert (GL(dl_rtld_map).l_libname->next == NULL);
+      GL(dl_rtld_map).l_libname->next = &newname;
+    }
+  /* The ld.so must be relocated since otherwise loading audit modules
+     will fail since they reuse the very same ld.so.  */
+  assert (GL(dl_rtld_map).l_relocated);
+
+  if (! rtld_is_main)
+    {
+      /* Extract the contents of the dynamic section for easy access.  */
+      elf_get_dynamic_info (main_map, NULL);
+      /* Set up our cache of pointers into the hash table.  */
+      _dl_setup_hash (main_map);
+    }
+
+  if (__builtin_expect (mode, normal) == verify)
+    {
+      /* We were called just to verify that this is a dynamic
+	 executable using us as the program interpreter.  Exit with an
+	 error if we were not able to load the binary or no interpreter
+	 is specified (i.e., this is no dynamically linked binary.  */
+      if (main_map->l_ld == NULL)
+	_exit (1);
+
+      /* We allow here some platform specific code.  */
+#ifdef DISTINGUISH_LIB_VERSIONS
+      DISTINGUISH_LIB_VERSIONS;
+#endif
+      _exit (has_interp ? 0 : 2);
+    }
+
+  struct link_map **first_preload = &GL(dl_rtld_map).l_next;
+  /* Set up the data structures for the system-supplied DSO early,
+     so they can influence _dl_init_paths.  */
+  setup_vdso (main_map, &first_preload);
+
+#ifdef DL_SYSDEP_OSCHECK
+  DL_SYSDEP_OSCHECK (_dl_fatal_printf);
+#endif
+
+  /* Initialize the data structures for the search paths for shared
+     objects.  */
+  _dl_init_paths (library_path);
+
+  /* Initialize _r_debug.  */
+  struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr,
+					    LM_ID_BASE);
+  r->r_state = RT_CONSISTENT;
+
+  /* Put the link_map for ourselves on the chain so it can be found by
+     name.  Note that at this point the global chain of link maps contains
+     exactly one element, which is pointed to by dl_loaded.  */
+  if (! GL(dl_rtld_map).l_name)
+    /* If not invoked directly, the dynamic linker shared object file was
+       found by the PT_INTERP name.  */
+    GL(dl_rtld_map).l_name = (char *) GL(dl_rtld_map).l_libname->name;
+  GL(dl_rtld_map).l_type = lt_library;
+  main_map->l_next = &GL(dl_rtld_map);
+  GL(dl_rtld_map).l_prev = main_map;
+  ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+  ++GL(dl_load_adds);
+
+  /* If LD_USE_LOAD_BIAS env variable has not been seen, default
+     to not using bias for non-prelinked PIEs and libraries
+     and using it for executables or prelinked PIEs or libraries.  */
+  if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2)
+    GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0;
+
+  /* Set up the program header information for the dynamic linker
+     itself.  It is needed in the dl_iterate_phdr callbacks.  */
+  const ElfW(Ehdr) *rtld_ehdr;
+
+  /* Starting from binutils-2.23, the linker will define the magic symbol
+     __ehdr_start to point to our own ELF header if it is visible in a
+     segment that also includes the phdrs.  If that's not available, we use
+     the old method that assumes the beginning of the file is part of the
+     lowest-addressed PT_LOAD segment.  */
+#ifdef HAVE_EHDR_START
+  extern const ElfW(Ehdr) __ehdr_start __attribute__ ((visibility ("hidden")));
+  rtld_ehdr = &__ehdr_start;
+#else
+  rtld_ehdr = (void *) GL(dl_rtld_map).l_map_start;
+#endif
+  assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
+  assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+
+  const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
+
+  GL(dl_rtld_map).l_phdr = rtld_phdr;
+  GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
+
+
+  /* PT_GNU_RELRO is usually the last phdr.  */
+  size_t cnt = rtld_ehdr->e_phnum;
+  while (cnt-- > 0)
+    if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
+      {
+	GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
+	GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
+	break;
+      }
+
+  /* Add the dynamic linker to the TLS list if it also uses TLS.  */
+  if (GL(dl_rtld_map).l_tls_blocksize != 0)
+    /* Assign a module ID.  Do this before loading any audit modules.  */
+    GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+
+  /* If we have auditing DSOs to load, do it now.  */
+  if (__glibc_unlikely (audit_list != NULL))
+    {
+      /* Iterate over all entries in the list.  The order is important.  */
+      struct audit_ifaces *last_audit = NULL;
+      struct audit_list *al = audit_list->next;
+
+      /* Since we start using the auditing DSOs right away we need to
+	 initialize the data structures now.  */
+      tcbp = init_tls ();
+
+      /* Initialize security features.  We need to do it this early
+	 since otherwise the constructors of the audit libraries will
+	 use different values (especially the pointer guard) and will
+	 fail later on.  */
+      security_init ();
+
+      do
+	{
+	  int tls_idx = GL(dl_tls_max_dtv_idx);
+
+	  /* Now it is time to determine the layout of the static TLS
+	     block and allocate it for the initial thread.  Note that we
+	     always allocate the static block, we never defer it even if
+	     no DF_STATIC_TLS bit is set.  The reason is that we know
+	     glibc will use the static model.  */
+	  struct dlmopen_args dlmargs;
+	  dlmargs.fname = al->name;
+	  dlmargs.map = NULL;
+
+	  const char *objname;
+	  const char *err_str = NULL;
+	  bool malloced;
+	  (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
+				  &dlmargs);
+	  if (__glibc_unlikely (err_str != NULL))
+	    {
+	    not_loaded:
+	      _dl_error_printf ("\
+ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+				al->name, err_str);
+	      if (malloced)
+		free ((char *) err_str);
+	    }
+	  else
+	    {
+	      struct lookup_args largs;
+	      largs.name = "la_version";
+	      largs.map = dlmargs.map;
+
+	      /* Check whether the interface version matches.  */
+	      (void) _dl_catch_error (&objname, &err_str, &malloced,
+				      lookup_doit, &largs);
+
+	      unsigned int (*laversion) (unsigned int);
+	      unsigned int lav;
+	      if  (err_str == NULL
+		   && (laversion = largs.result) != NULL
+		   && (lav = laversion (LAV_CURRENT)) > 0
+		   && lav <= LAV_CURRENT)
+		{
+		  /* Allocate structure for the callback function pointers.
+		     This call can never fail.  */
+		  union
+		  {
+		    struct audit_ifaces ifaces;
+#define naudit_ifaces 8
+		    void (*fptr[naudit_ifaces]) (void);
+		  } *newp = malloc (sizeof (*newp));
+
+		  /* Names of the auditing interfaces.  All in one
+		     long string.  */
+		  static const char audit_iface_names[] =
+		    "la_activity\0"
+		    "la_objsearch\0"
+		    "la_objopen\0"
+		    "la_preinit\0"
+#if __ELF_NATIVE_CLASS == 32
+		    "la_symbind32\0"
+#elif __ELF_NATIVE_CLASS == 64
+		    "la_symbind64\0"
+#else
+# error "__ELF_NATIVE_CLASS must be defined"
+#endif
+#define STRING(s) __STRING (s)
+		    "la_" STRING (ARCH_LA_PLTENTER) "\0"
+		    "la_" STRING (ARCH_LA_PLTEXIT) "\0"
+		    "la_objclose\0";
+		  unsigned int cnt = 0;
+		  const char *cp = audit_iface_names;
+		  do
+		    {
+		      largs.name = cp;
+		      (void) _dl_catch_error (&objname, &err_str, &malloced,
+					      lookup_doit, &largs);
+
+		      /* Store the pointer.  */
+		      if (err_str == NULL && largs.result != NULL)
+			{
+			  newp->fptr[cnt] = largs.result;
+
+			  /* The dynamic linker link map is statically
+			     allocated, initialize the data now.   */
+			  GL(dl_rtld_map).l_audit[cnt].cookie
+			    = (intptr_t) &GL(dl_rtld_map);
+			}
+		      else
+			newp->fptr[cnt] = NULL;
+		      ++cnt;
+
+		      cp = (char *) rawmemchr (cp, '\0') + 1;
+		    }
+		  while (*cp != '\0');
+		  assert (cnt == naudit_ifaces);
+
+		  /* Now append the new auditing interface to the list.  */
+		  newp->ifaces.next = NULL;
+		  if (last_audit == NULL)
+		    last_audit = GLRO(dl_audit) = &newp->ifaces;
+		  else
+		    last_audit = last_audit->next = &newp->ifaces;
+		  ++GLRO(dl_naudit);
+
+		  /* Mark the DSO as being used for auditing.  */
+		  dlmargs.map->l_auditing = 1;
+		}
+	      else
+		{
+		  /* We cannot use the DSO, it does not have the
+		     appropriate interfaces or it expects something
+		     more recent.  */
+#ifndef NDEBUG
+		  Lmid_t ns = dlmargs.map->l_ns;
+#endif
+		  _dl_close (dlmargs.map);
+
+		  /* Make sure the namespace has been cleared entirely.  */
+		  assert (GL(dl_ns)[ns]._ns_loaded == NULL);
+		  assert (GL(dl_ns)[ns]._ns_nloaded == 0);
+
+		  GL(dl_tls_max_dtv_idx) = tls_idx;
+		  goto not_loaded;
+		}
+	    }
+
+	  al = al->next;
+	}
+      while (al != audit_list->next);
+
+      /* If we have any auditing modules, announce that we already
+	 have two objects loaded.  */
+      if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+	{
+	  struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) };
+
+	  for (unsigned int outer = 0; outer < 2; ++outer)
+	    {
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  if (afct->objopen != NULL)
+		    {
+		      ls[outer]->l_audit[cnt].bindflags
+			= afct->objopen (ls[outer], LM_ID_BASE,
+					 &ls[outer]->l_audit[cnt].cookie);
+
+		      ls[outer]->l_audit_any_plt
+			|= ls[outer]->l_audit[cnt].bindflags != 0;
+		    }
+
+		  afct = afct->next;
+		}
+	    }
+	}
+    }
+
+  /* Keep track of the currently loaded modules to count how many
+     non-audit modules which use TLS are loaded.  */
+  size_t count_modids = _dl_count_modids ();
+
+  /* Set up debugging before the debugger is notified for the first time.  */
+#ifdef ELF_MACHINE_DEBUG_SETUP
+  /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way.  */
+  ELF_MACHINE_DEBUG_SETUP (main_map, r);
+  ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r);
+#else
+  if (main_map->l_info[DT_DEBUG] != NULL)
+    /* There is a DT_DEBUG entry in the dynamic section.  Fill it in
+       with the run-time address of the r_debug structure  */
+    main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+
+  /* Fill in the pointer in the dynamic linker's own dynamic section, in
+     case you run gdb on the dynamic linker directly.  */
+  if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL)
+    GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+#endif
+
+  /* We start adding objects.  */
+  r->r_state = RT_ADD;
+  _dl_debug_state ();
+  LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
+
+  /* Auditing checkpoint: we are ready to signal that the initial map
+     is being constructed.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->activity != NULL)
+	    afct->activity (&main_map->l_audit[cnt].cookie, LA_ACT_ADD);
+
+	  afct = afct->next;
+	}
+    }
+
+  /* We have two ways to specify objects to preload: via environment
+     variable and via the file /etc/ld.so.preload.  The latter can also
+     be used when security is enabled.  */
+  assert (*first_preload == NULL);
+  struct link_map **preloads = NULL;
+  unsigned int npreloads = 0;
+
+  if (__glibc_unlikely (preloadlist != NULL))
+    {
+      /* The LD_PRELOAD environment variable gives list of libraries
+	 separated by white space or colons that are loaded before the
+	 executable's dependencies and prepended to the global scope
+	 list.  If the binary is running setuid all elements
+	 containing a '/' are ignored since it is insecure.  */
+      char *list = strdupa (preloadlist);
+      char *p;
+
+      HP_TIMING_NOW (start);
+
+      /* Prevent optimizing strsep.  Speed is not important here.  */
+      while ((p = (strsep) (&list, " :")) != NULL)
+	if (p[0] != '\0'
+	    && (__builtin_expect (! __libc_enable_secure, 1)
+		|| strchr (p, '/') == NULL))
+	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
+
+      HP_TIMING_NOW (stop);
+      HP_TIMING_DIFF (diff, start, stop);
+      HP_TIMING_ACCUM_NT (load_time, diff);
+    }
+
+  /* There usually is no ld.so.preload file, it should only be used
+     for emergencies and testing.  So the open call etc should usually
+     fail.  Using access() on a non-existing file is faster than using
+     open().  So we do this first.  If it succeeds we do almost twice
+     the work but this does not matter, since it is not for production
+     use.  */
+  static const char preload_file[] = "/etc/ld.so.preload";
+  if (__glibc_unlikely (__access (preload_file, R_OK) == 0))
+    {
+      /* Read the contents of the file.  */
+      file = _dl_sysdep_read_whole_file (preload_file, &file_size,
+					 PROT_READ | PROT_WRITE);
+      if (__glibc_unlikely (file != MAP_FAILED))
+	{
+	  /* Parse the file.  It contains names of libraries to be loaded,
+	     separated by white spaces or `:'.  It may also contain
+	     comments introduced by `#'.  */
+	  char *problem;
+	  char *runp;
+	  size_t rest;
+
+	  /* Eliminate comments.  */
+	  runp = file;
+	  rest = file_size;
+	  while (rest > 0)
+	    {
+	      char *comment = memchr (runp, '#', rest);
+	      if (comment == NULL)
+		break;
+
+	      rest -= comment - runp;
+	      do
+		*comment = ' ';
+	      while (--rest > 0 && *++comment != '\n');
+	    }
+
+	  /* We have one problematic case: if we have a name at the end of
+	     the file without a trailing terminating characters, we cannot
+	     place the \0.  Handle the case separately.  */
+	  if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t'
+	      && file[file_size - 1] != '\n' && file[file_size - 1] != ':')
+	    {
+	      problem = &file[file_size];
+	      while (problem > file && problem[-1] != ' '
+		     && problem[-1] != '\t'
+		     && problem[-1] != '\n' && problem[-1] != ':')
+		--problem;
+
+	      if (problem > file)
+		problem[-1] = '\0';
+	    }
+	  else
+	    {
+	      problem = NULL;
+	      file[file_size - 1] = '\0';
+	    }
+
+	  HP_TIMING_NOW (start);
+
+	  if (file != problem)
+	    {
+	      char *p;
+	      runp = file;
+	      while ((p = strsep (&runp, ": \t\n")) != NULL)
+		if (p[0] != '\0')
+		  npreloads += do_preload (p, main_map, preload_file);
+	    }
+
+	  if (problem != NULL)
+	    {
+	      char *p = strndupa (problem, file_size - (problem - file));
+
+	      npreloads += do_preload (p, main_map, preload_file);
+	    }
+
+	  HP_TIMING_NOW (stop);
+	  HP_TIMING_DIFF (diff, start, stop);
+	  HP_TIMING_ACCUM_NT (load_time, diff);
+
+	  /* We don't need the file anymore.  */
+	  __munmap (file, file_size);
+	}
+    }
+
+  if (__glibc_unlikely (*first_preload != NULL))
+    {
+      /* Set up PRELOADS with a vector of the preloaded libraries.  */
+      struct link_map *l = *first_preload;
+      preloads = __alloca (npreloads * sizeof preloads[0]);
+      i = 0;
+      do
+	{
+	  preloads[i++] = l;
+	  l = l->l_next;
+	} while (l);
+      assert (i == npreloads);
+    }
+
+  /* Load all the libraries specified by DT_NEEDED entries.  If LD_PRELOAD
+     specified some libraries to load, these are inserted before the actual
+     dependencies in the executable's searchlist for symbol resolution.  */
+  HP_TIMING_NOW (start);
+  _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
+  HP_TIMING_NOW (stop);
+  HP_TIMING_DIFF (diff, start, stop);
+  HP_TIMING_ACCUM_NT (load_time, diff);
+
+  /* Mark all objects as being in the global scope.  */
+  for (i = main_map->l_searchlist.r_nlist; i > 0; )
+    main_map->l_searchlist.r_list[--i]->l_global = 1;
+
+  /* Remove _dl_rtld_map from the chain.  */
+  GL(dl_rtld_map).l_prev->l_next = GL(dl_rtld_map).l_next;
+  if (GL(dl_rtld_map).l_next != NULL)
+    GL(dl_rtld_map).l_next->l_prev = GL(dl_rtld_map).l_prev;
+
+  for (i = 1; i < main_map->l_searchlist.r_nlist; ++i)
+    if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map))
+      break;
+
+  bool rtld_multiple_ref = false;
+  if (__glibc_likely (i < main_map->l_searchlist.r_nlist))
+    {
+      /* Some DT_NEEDED entry referred to the interpreter object itself, so
+	 put it back in the list of visible objects.  We insert it into the
+	 chain in symbol search order because gdb uses the chain's order as
+	 its symbol search order.  */
+      rtld_multiple_ref = true;
+
+      GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
+      if (__builtin_expect (mode, normal) == normal)
+	{
+	  GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
+				    ? main_map->l_searchlist.r_list[i + 1]
+				    : NULL);
+#ifdef NEED_DL_SYSINFO_DSO
+	  if (GLRO(dl_sysinfo_map) != NULL
+	      && GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map)
+	      && GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map))
+	    GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map);
+#endif
+	}
+      else
+	/* In trace mode there might be an invisible object (which we
+	   could not find) after the previous one in the search list.
+	   In this case it doesn't matter much where we put the
+	   interpreter object, so we just initialize the list pointer so
+	   that the assertion below holds.  */
+	GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next;
+
+      assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next);
+      GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map);
+      if (GL(dl_rtld_map).l_next != NULL)
+	{
+	  assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev);
+	  GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map);
+	}
+    }
+
+  /* Now let us see whether all libraries are available in the
+     versions we need.  */
+  {
+    struct version_check_args args;
+    args.doexit = mode == normal;
+    args.dotrace = mode == trace;
+    _dl_receive_error (print_missing_version, version_check_doit, &args);
+  }
+
+  /* We do not initialize any of the TLS functionality unless any of the
+     initial modules uses TLS.  This makes dynamic loading of modules with
+     TLS impossible, but to support it requires either eagerly doing setup
+     now or lazily doing it later.  Doing it now makes us incompatible with
+     an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
+     used.  Trying to do it lazily is too hairy to try when there could be
+     multiple threads (from a non-TLS-using libpthread).  */
+  bool was_tls_init_tp_called = tls_init_tp_called;
+  if (tcbp == NULL)
+    tcbp = init_tls ();
+
+  if (__glibc_likely (audit_list == NULL))
+    /* Initialize security features.  But only if we have not done it
+       earlier.  */
+    security_init ();
+
+  if (__builtin_expect (mode, normal) != normal)
+    {
+      /* We were run just to list the shared libraries.  It is
+	 important that we do this before real relocation, because the
+	 functions we call below for output may no longer work properly
+	 after relocation.  */
+      struct link_map *l;
+
+      if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
+	{
+	  struct r_scope_elem *scope = &main_map->l_searchlist;
+
+	  for (i = 0; i < scope->r_nlist; i++)
+	    {
+	      l = scope->r_list [i];
+	      if (l->l_faked)
+		{
+		  _dl_printf ("\t%s => not found\n", l->l_libname->name);
+		  continue;
+		}
+	      if (_dl_name_match_p (GLRO(dl_trace_prelink), l))
+		GLRO(dl_trace_prelink_map) = l;
+	      _dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)",
+			  DSO_FILENAME (l->l_libname->name),
+			  DSO_FILENAME (l->l_name),
+			  (int) sizeof l->l_map_start * 2,
+			  (size_t) l->l_map_start,
+			  (int) sizeof l->l_addr * 2,
+			  (size_t) l->l_addr);
+
+	      if (l->l_tls_modid)
+		_dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid,
+			    (int) sizeof l->l_tls_offset * 2,
+			    (size_t) l->l_tls_offset);
+	      else
+		_dl_printf ("\n");
+	    }
+	}
+      else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
+	{
+	  /* Look through the dependencies of the main executable
+	     and determine which of them is not actually
+	     required.  */
+	  struct link_map *l = main_map;
+
+	  /* Relocate the main executable.  */
+	  struct relocate_args args = { .l = l,
+					.reloc_mode = ((GLRO(dl_lazy)
+						       ? RTLD_LAZY : 0)
+						       | __RTLD_NOIFUNC) };
+	  _dl_receive_error (print_unresolved, relocate_doit, &args);
+
+	  /* This loop depends on the dependencies of the executable to
+	     correspond in number and order to the DT_NEEDED entries.  */
+	  ElfW(Dyn) *dyn = main_map->l_ld;
+	  bool first = true;
+	  while (dyn->d_tag != DT_NULL)
+	    {
+	      if (dyn->d_tag == DT_NEEDED)
+		{
+		  l = l->l_next;
+#ifdef NEED_DL_SYSINFO_DSO
+		  /* Skip the VDSO since it's not part of the list
+		     of objects we brought in via DT_NEEDED entries.  */
+		  if (l == GLRO(dl_sysinfo_map))
+		    l = l->l_next;
+#endif
+		  if (!l->l_used)
+		    {
+		      if (first)
+			{
+			  _dl_printf ("Unused direct dependencies:\n");
+			  first = false;
+			}
+
+		      _dl_printf ("\t%s\n", l->l_name);
+		    }
+		}
+
+	      ++dyn;
+	    }
+
+	  _exit (first != true);
+	}
+      else if (! main_map->l_info[DT_NEEDED])
+	_dl_printf ("\tstatically linked\n");
+      else
+	{
+	  for (l = main_map->l_next; l; l = l->l_next)
+	    if (l->l_faked)
+	      /* The library was not found.  */
+	      _dl_printf ("\t%s => not found\n", l->l_libname->name);
+	    else if (strcmp (l->l_libname->name, l->l_name) == 0)
+	      _dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name,
+			  (int) sizeof l->l_map_start * 2,
+			  (size_t) l->l_map_start);
+	    else
+	      _dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name,
+			  l->l_name, (int) sizeof l->l_map_start * 2,
+			  (size_t) l->l_map_start);
+	}
+
+      if (__builtin_expect (mode, trace) != trace)
+	for (i = 1; i < (unsigned int) _dl_argc; ++i)
+	  {
+	    const ElfW(Sym) *ref = NULL;
+	    ElfW(Addr) loadbase;
+	    lookup_t result;
+
+	    result = _dl_lookup_symbol_x (_dl_argv[i], main_map,
+					  &ref, main_map->l_scope,
+					  NULL, ELF_RTYPE_CLASS_PLT,
+					  DL_LOOKUP_ADD_DEPENDENCY, NULL);
+
+	    loadbase = LOOKUP_VALUE_ADDRESS (result);
+
+	    _dl_printf ("%s found at 0x%0*Zd in object at 0x%0*Zd\n",
+			_dl_argv[i],
+			(int) sizeof ref->st_value * 2,
+			(size_t) ref->st_value,
+			(int) sizeof loadbase * 2, (size_t) loadbase);
+	  }
+      else
+	{
+	  /* If LD_WARN is set, warn about undefined symbols.  */
+	  if (GLRO(dl_lazy) >= 0 && GLRO(dl_verbose))
+	    {
+	      /* We have to do symbol dependency testing.  */
+	      struct relocate_args args;
+	      unsigned int i;
+
+	      args.reloc_mode = ((GLRO(dl_lazy) ? RTLD_LAZY : 0)
+				 | __RTLD_NOIFUNC);
+
+	      i = main_map->l_searchlist.r_nlist;
+	      while (i-- > 0)
+		{
+		  struct link_map *l = main_map->l_initfini[i];
+		  if (l != &GL(dl_rtld_map) && ! l->l_faked)
+		    {
+		      args.l = l;
+		      _dl_receive_error (print_unresolved, relocate_doit,
+					 &args);
+		    }
+		}
+
+	      if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
+		  && rtld_multiple_ref)
+		{
+		  /* Mark the link map as not yet relocated again.  */
+		  GL(dl_rtld_map).l_relocated = 0;
+		  _dl_relocate_object (&GL(dl_rtld_map),
+				       main_map->l_scope, __RTLD_NOIFUNC, 0);
+		}
+	    }
+#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
+	  if (version_info)
+	    {
+	      /* Print more information.  This means here, print information
+		 about the versions needed.  */
+	      int first = 1;
+	      struct link_map *map;
+
+	      for (map = main_map; map != NULL; map = map->l_next)
+		{
+		  const char *strtab;
+		  ElfW(Dyn) *dyn = map->l_info[VERNEEDTAG];
+		  ElfW(Verneed) *ent;
+
+		  if (dyn == NULL)
+		    continue;
+
+		  strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+		  ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
+
+		  if (first)
+		    {
+		      _dl_printf ("\n\tVersion information:\n");
+		      first = 0;
+		    }
+
+		  _dl_printf ("\t%s:\n", DSO_FILENAME (map->l_name));
+
+		  while (1)
+		    {
+		      ElfW(Vernaux) *aux;
+		      struct link_map *needed;
+
+		      needed = find_needed (strtab + ent->vn_file);
+		      aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
+
+		      while (1)
+			{
+			  const char *fname = NULL;
+
+			  if (needed != NULL
+			      && match_version (strtab + aux->vna_name,
+						needed))
+			    fname = needed->l_name;
+
+			  _dl_printf ("\t\t%s (%s) %s=> %s\n",
+				      strtab + ent->vn_file,
+				      strtab + aux->vna_name,
+				      aux->vna_flags & VER_FLG_WEAK
+				      ? "[WEAK] " : "",
+				      fname ?: "not found");
+
+			  if (aux->vna_next == 0)
+			    /* No more symbols.  */
+			    break;
+
+			  /* Next symbol.  */
+			  aux = (ElfW(Vernaux) *) ((char *) aux
+						   + aux->vna_next);
+			}
+
+		      if (ent->vn_next == 0)
+			/* No more dependencies.  */
+			break;
+
+		      /* Next dependency.  */
+		      ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
+		    }
+		}
+	    }
+	}
+
+      _exit (0);
+    }
+
+  if (main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]
+      && ! __builtin_expect (GLRO(dl_profile) != NULL, 0)
+      && ! __builtin_expect (GLRO(dl_dynamic_weak), 0))
+    {
+      ElfW(Lib) *liblist, *liblistend;
+      struct link_map **r_list, **r_listend, *l;
+      const char *strtab = (const void *) D_PTR (main_map, l_info[DT_STRTAB]);
+
+      assert (main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)] != NULL);
+      liblist = (ElfW(Lib) *)
+		main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr;
+      liblistend = (ElfW(Lib) *)
+		   ((char *) liblist +
+		    main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val);
+      r_list = main_map->l_searchlist.r_list;
+      r_listend = r_list + main_map->l_searchlist.r_nlist;
+
+      for (; r_list < r_listend && liblist < liblistend; r_list++)
+	{
+	  l = *r_list;
+
+	  if (l == main_map)
+	    continue;
+
+	  /* If the library is not mapped where it should, fail.  */
+	  if (l->l_addr)
+	    break;
+
+	  /* Next, check if checksum matches.  */
+	  if (l->l_info [VALIDX(DT_CHECKSUM)] == NULL
+	      || l->l_info [VALIDX(DT_CHECKSUM)]->d_un.d_val
+		 != liblist->l_checksum)
+	    break;
+
+	  if (l->l_info [VALIDX(DT_GNU_PRELINKED)] == NULL
+	      || l->l_info [VALIDX(DT_GNU_PRELINKED)]->d_un.d_val
+		 != liblist->l_time_stamp)
+	    break;
+
+	  if (! _dl_name_match_p (strtab + liblist->l_name, l))
+	    break;
+
+	  ++liblist;
+	}
+
+
+      if (r_list == r_listend && liblist == liblistend)
+	prelinked = true;
+
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+	_dl_debug_printf ("\nprelink checking: %s\n",
+			  prelinked ? "ok" : "failed");
+    }
+
+
+  /* Now set up the variable which helps the assembler startup code.  */
+  GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist;
+
+  /* Save the information about the original global scope list since
+     we need it in the memory handling later.  */
+  GLRO(dl_initial_searchlist) = *GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist;
+
+  /* Remember the last search directory added at startup, now that
+     malloc will no longer be the one from dl-minimal.c.  */
+  GLRO(dl_init_all_dirs) = GL(dl_all_dirs);
+
+  /* Print scope information.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
+    {
+      _dl_debug_printf ("\nInitial object scopes\n");
+
+      for (struct link_map *l = main_map; l != NULL; l = l->l_next)
+	_dl_show_scope (l, 0);
+    }
+
+  if (prelinked)
+    {
+      if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
+	{
+	  ElfW(Rela) *conflict, *conflictend;
+#ifndef HP_TIMING_NONAVAIL
+	  hp_timing_t start;
+	  hp_timing_t stop;
+#endif
+
+	  HP_TIMING_NOW (start);
+	  assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL);
+	  conflict = (ElfW(Rela) *)
+	    main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr;
+	  conflictend = (ElfW(Rela) *)
+	    ((char *) conflict
+	     + main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val);
+	  _dl_resolve_conflicts (main_map, conflict, conflictend);
+	  HP_TIMING_NOW (stop);
+	  HP_TIMING_DIFF (relocate_time, start, stop);
+	}
+
+
+      /* Mark all the objects so we know they have been already relocated.  */
+      for (struct link_map *l = main_map; l != NULL; l = l->l_next)
+	{
+	  l->l_relocated = 1;
+	  if (l->l_relro_size)
+	    _dl_protect_relro (l);
+
+	  /* Add object to slot information data if necessasy.  */
+	  if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+	    _dl_add_to_slotinfo (l);
+	}
+    }
+  else
+    {
+      /* Now we have all the objects loaded.  Relocate them all except for
+	 the dynamic linker itself.  We do this in reverse order so that copy
+	 relocs of earlier objects overwrite the data written by later
+	 objects.  We do not re-relocate the dynamic linker itself in this
+	 loop because that could result in the GOT entries for functions we
+	 call being changed, and that would break us.  It is safe to relocate
+	 the dynamic linker out of order because it has no copy relocs (we
+	 know that because it is self-contained).  */
+
+      int consider_profiling = GLRO(dl_profile) != NULL;
+#ifndef HP_TIMING_NONAVAIL
+      hp_timing_t start;
+      hp_timing_t stop;
+#endif
+
+      /* If we are profiling we also must do lazy reloaction.  */
+      GLRO(dl_lazy) |= consider_profiling;
+
+      HP_TIMING_NOW (start);
+      unsigned i = main_map->l_searchlist.r_nlist;
+      while (i-- > 0)
+	{
+	  struct link_map *l = main_map->l_initfini[i];
+
+	  /* While we are at it, help the memory handling a bit.  We have to
+	     mark some data structures as allocated with the fake malloc()
+	     implementation in ld.so.  */
+	  struct libname_list *lnp = l->l_libname->next;
+
+	  while (__builtin_expect (lnp != NULL, 0))
+	    {
+	      lnp->dont_free = 1;
+	      lnp = lnp->next;
+	    }
+	  /* Also allocated with the fake malloc().  */
+	  l->l_free_initfini = 0;
+
+	  if (l != &GL(dl_rtld_map))
+	    _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
+				 consider_profiling);
+
+	  /* Add object to slot information data if necessasy.  */
+	  if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+	    _dl_add_to_slotinfo (l);
+	}
+      HP_TIMING_NOW (stop);
+
+      HP_TIMING_DIFF (relocate_time, start, stop);
+
+      /* Now enable profiling if needed.  Like the previous call,
+	 this has to go here because the calls it makes should use the
+	 rtld versions of the functions (particularly calloc()), but it
+	 needs to have _dl_profile_map set up by the relocator.  */
+      if (__glibc_unlikely (GL(dl_profile_map) != NULL))
+	/* We must prepare the profiling.  */
+	_dl_start_profile ();
+    }
+
+  if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
+      || count_modids != _dl_count_modids ())
+    ++GL(dl_tls_generation);
+
+  /* Now that we have completed relocation, the initializer data
+     for the TLS blocks has its final values and we can copy them
+     into the main thread's TLS area, which we allocated above.  */
+  _dl_allocate_tls_init (tcbp);
+
+  /* And finally install it for the main thread.  */
+  if (! tls_init_tp_called)
+    {
+      const char *lossage = TLS_INIT_TP (tcbp);
+      if (__glibc_unlikely (lossage != NULL))
+	_dl_fatal_printf ("cannot set up thread-local storage: %s\n",
+			  lossage);
+    }
+
+  /* Make sure no new search directories have been added.  */
+  assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs));
+
+  if (! prelinked && rtld_multiple_ref)
+    {
+      /* There was an explicit ref to the dynamic linker as a shared lib.
+	 Re-relocate ourselves with user-controlled symbol definitions.
+
+	 We must do this after TLS initialization in case after this
+	 re-relocation, we might call a user-supplied function
+	 (e.g. calloc from _dl_relocate_object) that uses TLS data.  */
+
+#ifndef HP_TIMING_NONAVAIL
+      hp_timing_t start;
+      hp_timing_t stop;
+      hp_timing_t add;
+#endif
+
+      HP_TIMING_NOW (start);
+      /* Mark the link map as not yet relocated again.  */
+      GL(dl_rtld_map).l_relocated = 0;
+      _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
+      HP_TIMING_NOW (stop);
+      HP_TIMING_DIFF (add, start, stop);
+      HP_TIMING_ACCUM_NT (relocate_time, add);
+    }
+
+  /* Do any necessary cleanups for the startup OS interface code.
+     We do these now so that no calls are made after rtld re-relocation
+     which might be resolved to different functions than we expect.
+     We cannot do this before relocating the other objects because
+     _dl_relocate_object might need to call `mprotect' for DT_TEXTREL.  */
+  _dl_sysdep_start_cleanup ();
+
+#ifdef SHARED
+  /* Auditing checkpoint: we have added all objects.  */
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+    {
+      struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+      /* Do not call the functions for any auditing object.  */
+      if (head->l_auditing == 0)
+	{
+	  struct audit_ifaces *afct = GLRO(dl_audit);
+	  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	    {
+	      if (afct->activity != NULL)
+		afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+	      afct = afct->next;
+	    }
+	}
+    }
+#endif
+
+  /* Notify the debugger all new objects are now ready to go.  We must re-get
+     the address since by now the variable might be in another object.  */
+  r = _dl_debug_initialize (0, LM_ID_BASE);
+  r->r_state = RT_CONSISTENT;
+  _dl_debug_state ();
+  LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
+
+#if defined USE_LDCONFIG && !defined MAP_COPY
+  /* We must munmap() the cache file.  */
+  _dl_unload_cache ();
+#endif
+
+  /* Once we return, _dl_sysdep_start will invoke
+     the DT_INIT functions and then *USER_ENTRY.  */
+}
+
+/* This is a little helper function for resolving symbols while
+   tracing the binary.  */
+static void
+print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
+		  const char *errstring)
+{
+  if (objname[0] == '\0')
+    objname = RTLD_PROGNAME;
+  _dl_error_printf ("%s	(%s)\n", errstring, objname);
+}
+
+/* This is a little helper function for resolving symbols while
+   tracing the binary.  */
+static void
+print_missing_version (int errcode __attribute__ ((unused)),
+		       const char *objname, const char *errstring)
+{
+  _dl_error_printf ("%s: %s: %s\n", RTLD_PROGNAME,
+		    objname, errstring);
+}
+
+/* Nonzero if any of the debugging options is enabled.  */
+static int any_debug attribute_relro;
+
+/* Process the string given as the parameter which explains which debugging
+   options are enabled.  */
+static void
+process_dl_debug (const char *dl_debug)
+{
+  /* When adding new entries make sure that the maximal length of a name
+     is correctly handled in the LD_DEBUG_HELP code below.  */
+  static const struct
+  {
+    unsigned char len;
+    const char name[10];
+    const char helptext[41];
+    unsigned short int mask;
+  } debopts[] =
+    {
+#define LEN_AND_STR(str) sizeof (str) - 1, str
+      { LEN_AND_STR ("libs"), "display library search paths",
+	DL_DEBUG_LIBS | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("reloc"), "display relocation processing",
+	DL_DEBUG_RELOC | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("files"), "display progress for input file",
+	DL_DEBUG_FILES | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("symbols"), "display symbol table processing",
+	DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("bindings"), "display information about symbol binding",
+	DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("versions"), "display version dependencies",
+	DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("scopes"), "display scope information",
+	DL_DEBUG_SCOPES },
+      { LEN_AND_STR ("all"), "all previous options combined",
+	DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
+	| DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS
+	| DL_DEBUG_SCOPES },
+      { LEN_AND_STR ("statistics"), "display relocation statistics",
+	DL_DEBUG_STATISTICS },
+      { LEN_AND_STR ("unused"), "determined unused DSOs",
+	DL_DEBUG_UNUSED },
+      { LEN_AND_STR ("help"), "display this help message and exit",
+	DL_DEBUG_HELP },
+    };
+#define ndebopts (sizeof (debopts) / sizeof (debopts[0]))
+
+  /* Skip separating white spaces and commas.  */
+  while (*dl_debug != '\0')
+    {
+      if (*dl_debug != ' ' && *dl_debug != ',' && *dl_debug != ':')
+	{
+	  size_t cnt;
+	  size_t len = 1;
+
+	  while (dl_debug[len] != '\0' && dl_debug[len] != ' '
+		 && dl_debug[len] != ',' && dl_debug[len] != ':')
+	    ++len;
+
+	  for (cnt = 0; cnt < ndebopts; ++cnt)
+	    if (debopts[cnt].len == len
+		&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
+	      {
+		GLRO(dl_debug_mask) |= debopts[cnt].mask;
+		any_debug = 1;
+		break;
+	      }
+
+	  if (cnt == ndebopts)
+	    {
+	      /* Display a warning and skip everything until next
+		 separator.  */
+	      char *copy = strndupa (dl_debug, len);
+	      _dl_error_printf ("\
+warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
+	    }
+
+	  dl_debug += len;
+	  continue;
+	}
+
+      ++dl_debug;
+    }
+
+  if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
+    {
+      /* In order to get an accurate picture of whether a particular
+	 DT_NEEDED entry is actually used we have to process both
+	 the PLT and non-PLT relocation entries.  */
+      GLRO(dl_lazy) = 0;
+    }
+
+  if (GLRO(dl_debug_mask) & DL_DEBUG_HELP)
+    {
+      size_t cnt;
+
+      _dl_printf ("\
+Valid options for the LD_DEBUG environment variable are:\n\n");
+
+      for (cnt = 0; cnt < ndebopts; ++cnt)
+	_dl_printf ("  %.*s%s%s\n", debopts[cnt].len, debopts[cnt].name,
+		    "         " + debopts[cnt].len - 3,
+		    debopts[cnt].helptext);
+
+      _dl_printf ("\n\
+To direct the debugging output into a file instead of standard output\n\
+a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
+      _exit (0);
+    }
+}
+
+static void
+process_dl_audit (char *str)
+{
+  /* The parameter is a colon separated list of DSO names.  */
+  char *p;
+
+  while ((p = (strsep) (&str, ":")) != NULL)
+    if (p[0] != '\0'
+	&& (__builtin_expect (! __libc_enable_secure, 1)
+	    || strchr (p, '/') == NULL))
+      {
+	/* This is using the local malloc, not the system malloc.  The
+	   memory can never be freed.  */
+	struct audit_list *newp = malloc (sizeof (*newp));
+	newp->name = p;
+
+	if (audit_list == NULL)
+	  audit_list = newp->next = newp;
+	else
+	  {
+	    newp->next = audit_list->next;
+	    audit_list = audit_list->next = newp;
+	  }
+      }
+}
+
+/* Process all environments variables the dynamic linker must recognize.
+   Since all of them start with `LD_' we are a bit smarter while finding
+   all the entries.  */
+extern char **_environ attribute_hidden;
+
+
+static void
+process_envvars (enum mode *modep)
+{
+  char **runp = _environ;
+  char *envline;
+  enum mode mode = normal;
+  char *debug_output = NULL;
+
+  /* This is the default place for profiling data file.  */
+  GLRO(dl_profile_output)
+    = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];
+
+  while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
+    {
+      size_t len = 0;
+
+      while (envline[len] != '\0' && envline[len] != '=')
+	++len;
+
+      if (envline[len] != '=')
+	/* This is a "LD_" variable at the end of the string without
+	   a '=' character.  Ignore it since otherwise we will access
+	   invalid memory below.  */
+	continue;
+
+      switch (len)
+	{
+	case 4:
+	  /* Warning level, verbose or not.  */
+	  if (memcmp (envline, "WARN", 4) == 0)
+	    GLRO(dl_verbose) = envline[5] != '\0';
+	  break;
+
+	case 5:
+	  /* Debugging of the dynamic linker?  */
+	  if (memcmp (envline, "DEBUG", 5) == 0)
+	    {
+	      process_dl_debug (&envline[6]);
+	      break;
+	    }
+	  if (memcmp (envline, "AUDIT", 5) == 0)
+	    process_dl_audit (&envline[6]);
+	  break;
+
+	case 7:
+	  /* Print information about versions.  */
+	  if (memcmp (envline, "VERBOSE", 7) == 0)
+	    {
+	      version_info = envline[8] != '\0';
+	      break;
+	    }
+
+	  /* List of objects to be preloaded.  */
+	  if (memcmp (envline, "PRELOAD", 7) == 0)
+	    {
+	      preloadlist = &envline[8];
+	      break;
+	    }
+
+	  /* Which shared object shall be profiled.  */
+	  if (memcmp (envline, "PROFILE", 7) == 0 && envline[8] != '\0')
+	    GLRO(dl_profile) = &envline[8];
+	  break;
+
+	case 8:
+	  /* Do we bind early?  */
+	  if (memcmp (envline, "BIND_NOW", 8) == 0)
+	    {
+	      GLRO(dl_lazy) = envline[9] == '\0';
+	      break;
+	    }
+	  if (memcmp (envline, "BIND_NOT", 8) == 0)
+	    GLRO(dl_bind_not) = envline[9] != '\0';
+	  break;
+
+	case 9:
+	  /* Test whether we want to see the content of the auxiliary
+	     array passed up from the kernel.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "SHOW_AUXV", 9) == 0)
+	    _dl_show_auxv ();
+	  break;
+
+#if !HAVE_TUNABLES
+	case 10:
+	  /* Mask for the important hardware capabilities.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "HWCAP_MASK", 10) == 0)
+	    GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
+						      0, 0);
+	  break;
+#endif
+
+	case 11:
+	  /* Path where the binary is found.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "ORIGIN_PATH", 11) == 0)
+	    GLRO(dl_origin_path) = &envline[12];
+	  break;
+
+	case 12:
+	  /* The library search path.  */
+	  if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
+	    {
+	      library_path = &envline[13];
+	      break;
+	    }
+
+	  /* Where to place the profiling data file.  */
+	  if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0)
+	    {
+	      debug_output = &envline[13];
+	      break;
+	    }
+
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
+	    GLRO(dl_dynamic_weak) = 1;
+	  break;
+
+	case 13:
+	  /* We might have some extra environment variable with length 13
+	     to handle.  */
+#ifdef EXTRA_LD_ENVVARS_13
+	  EXTRA_LD_ENVVARS_13
+#endif
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
+	    {
+	      GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
+	      break;
+	    }
+	  break;
+
+	case 14:
+	  /* Where to place the profiling data file.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "PROFILE_OUTPUT", 14) == 0
+	      && envline[15] != '\0')
+	    GLRO(dl_profile_output) = &envline[15];
+	  break;
+
+	case 16:
+	  /* The mode of the dynamic linker can be set.  */
+	  if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
+	    {
+	      mode = trace;
+	      GLRO(dl_verbose) = 1;
+	      GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
+	      GLRO(dl_trace_prelink) = &envline[17];
+	    }
+	  break;
+
+	case 20:
+	  /* The mode of the dynamic linker can be set.  */
+	  if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
+	    mode = trace;
+	  break;
+
+	  /* We might have some extra environment variable to handle.  This
+	     is tricky due to the pre-processing of the length of the name
+	     in the switch statement here.  The code here assumes that added
+	     environment variables have a different length.  */
+#ifdef EXTRA_LD_ENVVARS
+	  EXTRA_LD_ENVVARS
+#endif
+	}
+    }
+
+  /* The caller wants this information.  */
+  *modep = mode;
+
+  /* Extra security for SUID binaries.  Remove all dangerous environment
+     variables.  */
+  if (__builtin_expect (__libc_enable_secure, 0))
+    {
+      static const char unsecure_envvars[] =
+#ifdef EXTRA_UNSECURE_ENVVARS
+	EXTRA_UNSECURE_ENVVARS
+#endif
+	UNSECURE_ENVVARS;
+      const char *nextp;
+
+      nextp = unsecure_envvars;
+      do
+	{
+	  unsetenv (nextp);
+	  /* We could use rawmemchr but this need not be fast.  */
+	  nextp = (char *) (strchr) (nextp, '\0') + 1;
+	}
+      while (*nextp != '\0');
+
+      if (__access ("/etc/suid-debug", F_OK) != 0)
+	{
+#if !HAVE_TUNABLES
+	  unsetenv ("MALLOC_CHECK_");
+#endif
+	  GLRO(dl_debug_mask) = 0;
+	}
+
+      if (mode != normal)
+	_exit (5);
+    }
+  /* If we have to run the dynamic linker in debugging mode and the
+     LD_DEBUG_OUTPUT environment variable is given, we write the debug
+     messages to this file.  */
+  else if (any_debug && debug_output != NULL)
+    {
+      const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW;
+      size_t name_len = strlen (debug_output);
+      char buf[name_len + 12];
+      char *startp;
+
+      buf[name_len + 11] = '\0';
+      startp = _itoa (__getpid (), &buf[name_len + 11], 10, 0);
+      *--startp = '.';
+      startp = memcpy (startp - name_len, debug_output, name_len);
+
+      GLRO(dl_debug_fd) = __open (startp, flags, DEFFILEMODE);
+      if (GLRO(dl_debug_fd) == -1)
+	/* We use standard output if opening the file failed.  */
+	GLRO(dl_debug_fd) = STDOUT_FILENO;
+    }
+}
+
+
+/* Print the various times we collected.  */
+static void
+__attribute ((noinline))
+print_statistics (hp_timing_t *rtld_total_timep)
+{
+#ifndef HP_TIMING_NONAVAIL
+  char buf[200];
+  char *cp;
+  char *wp;
+
+  /* Total time rtld used.  */
+  if (HP_SMALL_TIMING_AVAIL)
+    {
+      HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep);
+      _dl_debug_printf ("\nruntime linker statistics:\n"
+			"  total startup time in dynamic loader: %s\n", buf);
+
+      /* Print relocation statistics.  */
+      char pbuf[30];
+      HP_TIMING_PRINT (buf, sizeof (buf), relocate_time);
+      cp = _itoa ((1000ULL * relocate_time) / *rtld_total_timep,
+		  pbuf + sizeof (pbuf), 10, 0);
+      wp = pbuf;
+      switch (pbuf + sizeof (pbuf) - cp)
+	{
+	case 3:
+	  *wp++ = *cp++;
+	case 2:
+	  *wp++ = *cp++;
+	case 1:
+	  *wp++ = '.';
+	  *wp++ = *cp++;
+	}
+      *wp = '\0';
+      _dl_debug_printf ("\
+	    time needed for relocation: %s (%s%%)\n", buf, pbuf);
+    }
+#endif
+
+  unsigned long int num_relative_relocations = 0;
+  for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
+    {
+      if (GL(dl_ns)[ns]._ns_loaded == NULL)
+	continue;
+
+      struct r_scope_elem *scope = &GL(dl_ns)[ns]._ns_loaded->l_searchlist;
+
+      for (unsigned int i = 0; i < scope->r_nlist; i++)
+	{
+	  struct link_map *l = scope->r_list [i];
+
+	  if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELCOUNT)])
+	    num_relative_relocations
+	      += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val;
+#ifndef ELF_MACHINE_REL_RELATIVE
+	  /* Relative relocations are processed on these architectures if
+	     library is loaded to different address than p_vaddr or
+	     if not prelinked.  */
+	  if ((l->l_addr != 0 || !l->l_info[VALIDX(DT_GNU_PRELINKED)])
+	      && l->l_info[VERSYMIDX (DT_RELACOUNT)])
+#else
+	  /* On e.g. IA-64 or Alpha, relative relocations are processed
+	     only if library is loaded to different address than p_vaddr.  */
+	  if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELACOUNT)])
+#endif
+	    num_relative_relocations
+	      += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val;
+	}
+    }
+
+  _dl_debug_printf ("                 number of relocations: %lu\n"
+		    "      number of relocations from cache: %lu\n"
+		    "        number of relative relocations: %lu\n",
+		    GL(dl_num_relocations),
+		    GL(dl_num_cache_relocations),
+		    num_relative_relocations);
+
+#ifndef HP_TIMING_NONAVAIL
+  /* Time spend while loading the object and the dependencies.  */
+  if (HP_SMALL_TIMING_AVAIL)
+    {
+      char pbuf[30];
+      HP_TIMING_PRINT (buf, sizeof (buf), load_time);
+      cp = _itoa ((1000ULL * load_time) / *rtld_total_timep,
+		  pbuf + sizeof (pbuf), 10, 0);
+      wp = pbuf;
+      switch (pbuf + sizeof (pbuf) - cp)
+	{
+	case 3:
+	  *wp++ = *cp++;
+	case 2:
+	  *wp++ = *cp++;
+	case 1:
+	  *wp++ = '.';
+	  *wp++ = *cp++;
+	}
+      *wp = '\0';
+      _dl_debug_printf ("\
+	   time needed to load objects: %s (%s%%)\n",
+				buf, pbuf);
+    }
+#endif
+}
diff --git a/REORG.TODO/elf/setup-vdso.h b/REORG.TODO/elf/setup-vdso.h
new file mode 100644
index 0000000000..2db597eba3
--- /dev/null
+++ b/REORG.TODO/elf/setup-vdso.h
@@ -0,0 +1,121 @@
+/* Set up the data structures for the system-supplied DSO.
+   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+static inline void __attribute__ ((always_inline))
+setup_vdso (struct link_map *main_map __attribute__ ((unused)),
+	    struct link_map ***first_preload __attribute__ ((unused)))
+{
+#ifdef NEED_DL_SYSINFO_DSO
+  if (GLRO(dl_sysinfo_dso) == NULL)
+    return;
+
+  /* Do an abridged version of the work _dl_map_object_from_fd would do
+     to map in the object.  It's already mapped and prelinked (and
+     better be, since it's read-only and so we couldn't relocate it).
+     We just want our data structures to describe it as if we had just
+     mapped and relocated it normally.  */
+  struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
+				       0, LM_ID_BASE);
+  if (__glibc_likely (l != NULL))
+    {
+      static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
+
+      l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
+		   + GLRO(dl_sysinfo_dso)->e_phoff);
+      l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
+      for (uint_fast16_t i = 0; i < l->l_phnum; ++i)
+	{
+	  const ElfW(Phdr) *const ph = &l->l_phdr[i];
+	  if (ph->p_type == PT_DYNAMIC)
+	    {
+	      l->l_ld = (void *) ph->p_vaddr;
+	      l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+	    }
+	  else if (ph->p_type == PT_LOAD)
+	    {
+	      if (! l->l_addr)
+		l->l_addr = ph->p_vaddr;
+	      if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
+		l->l_map_end = ph->p_vaddr + ph->p_memsz;
+	      if ((ph->p_flags & PF_X)
+		  && ph->p_vaddr + ph->p_memsz >= l->l_text_end)
+		l->l_text_end = ph->p_vaddr + ph->p_memsz;
+	    }
+	  else
+	    /* There must be no TLS segment.  */
+	    assert (ph->p_type != PT_TLS);
+	}
+      l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso);
+      l->l_addr = l->l_map_start - l->l_addr;
+      l->l_map_end += l->l_addr;
+      l->l_text_end += l->l_addr;
+      l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+      elf_get_dynamic_info (l, dyn_temp);
+      _dl_setup_hash (l);
+      l->l_relocated = 1;
+
+      /* The vDSO is always used.  */
+      l->l_used = 1;
+
+      /* Initialize l_local_scope to contain just this map.  This allows
+	 the use of dl_lookup_symbol_x to resolve symbols within the vdso.
+	 So we create a single entry list pointing to l_real as its only
+	 element */
+      l->l_local_scope[0]->r_nlist = 1;
+      l->l_local_scope[0]->r_list = &l->l_real;
+
+      /* Now that we have the info handy, use the DSO image's soname
+	 so this object can be looked up by name.  Note that we do not
+	 set l_name here.  That field gives the file name of the DSO,
+	 and this DSO is not associated with any file.  */
+      if (l->l_info[DT_SONAME] != NULL)
+	{
+	  /* Work around a kernel problem.  The kernel cannot handle
+	     addresses in the vsyscall DSO pages in writev() calls.  */
+	  const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
+				 + l->l_info[DT_SONAME]->d_un.d_val);
+	  size_t len = strlen (dsoname) + 1;
+	  char *copy = malloc (len);
+	  if (copy == NULL)
+	    _dl_fatal_printf ("out of memory\n");
+	  l->l_libname->name = l->l_name = memcpy (copy, dsoname, len);
+	}
+
+      /* Add the vDSO to the object list.  */
+      _dl_add_to_namespace_list (l, LM_ID_BASE);
+
+# if IS_IN (rtld)
+      /* Rearrange the list so this DSO appears after rtld_map.  */
+      assert (l->l_next == NULL);
+      assert (l->l_prev == main_map);
+      GL(dl_rtld_map).l_next = l;
+      l->l_prev = &GL(dl_rtld_map);
+      *first_preload = &l->l_next;
+# else
+      GL(dl_nns) = 1;
+# endif
+
+      /* We have a prelinked DSO preloaded by the system.  */
+      GLRO(dl_sysinfo_map) = l;
+# ifdef NEED_DL_SYSINFO
+      if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT)
+	GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr;
+# endif
+    }
+#endif
+}
diff --git a/REORG.TODO/elf/sln.c b/REORG.TODO/elf/sln.c
new file mode 100644
index 0000000000..af2d0de164
--- /dev/null
+++ b/REORG.TODO/elf/sln.c
@@ -0,0 +1,202 @@
+/* `sln' program to create symbolic links between files.
+   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <error.h>
+#include <errno.h>
+#include <libintl.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "../version.h"
+
+#define PACKAGE _libc_intl_domainname
+
+static int makesymlink (const char *src, const char *dest);
+static int makesymlinks (const char *file);
+static void usage (void);
+
+int
+main (int argc, char **argv)
+{
+  /* Set locale via LC_ALL.  */
+  setlocale (LC_ALL, "");
+
+  /* Set the text message domain.  */
+  textdomain (PACKAGE);
+
+  switch (argc)
+    {
+    case 2:
+      if (strcmp (argv[1], "--version") == 0) {
+	printf ("sln %s%s\n", PKGVERSION, VERSION);
+	return 0;
+      } else if (strcmp (argv[1], "--help") == 0) {
+	usage ();
+	return 0;
+      }
+      return makesymlinks (argv [1]);
+      break;
+
+    case 3:
+      return makesymlink (argv [1], argv [2]);
+      break;
+
+    default:
+      usage ();
+      return 1;
+      break;
+    }
+}
+
+static void
+usage (void)
+{
+  printf (_("Usage: sln src dest|file\n\n"));
+  printf (_("For bug reporting instructions, please see:\n\
+%s.\n"), REPORT_BUGS_TO);
+}
+
+static int
+makesymlinks (const char *file)
+{
+  char *buffer = NULL;
+  size_t bufferlen = 0;
+  int ret;
+  int lineno;
+  FILE *fp;
+
+  if (strcmp (file, "-") == 0)
+    fp = stdin;
+  else
+    {
+      fp = fopen (file, "r");
+      if (fp == NULL)
+	{
+	  fprintf (stderr, _("%s: file open error: %m\n"), file);
+	  return 1;
+	}
+    }
+
+  ret = 0;
+  lineno = 0;
+  while (!feof_unlocked (fp))
+    {
+      ssize_t n = getline (&buffer, &bufferlen, fp);
+      char *src;
+      char *dest;
+      char *cp = buffer;
+
+      if (n < 0)
+	break;
+      if (buffer[n - 1] == '\n')
+	buffer[n - 1] = '\0';
+
+      ++lineno;
+      while (isspace (*cp))
+	++cp;
+      if (*cp == '\0')
+	/* Ignore empty lines.  */
+	continue;
+      src = cp;
+
+      do
+	++cp;
+      while (*cp != '\0' && ! isspace (*cp));
+      if (*cp != '\0')
+	*cp++ = '\0';
+
+      while (isspace (*cp))
+	++cp;
+      if (*cp == '\0')
+	{
+	  fprintf (stderr, _("No target in line %d\n"), lineno);
+	  ret = 1;
+	  continue;
+	}
+      dest = cp;
+
+      do
+	++cp;
+      while (*cp != '\0' && ! isspace (*cp));
+      if (*cp != '\0')
+	*cp++ = '\0';
+
+      ret |= makesymlink (src, dest);
+    }
+  fclose (fp);
+
+  return ret;
+}
+
+static int
+makesymlink (const char *src, const char *dest)
+{
+  struct stat64 stats;
+  const char *error;
+
+  /* Destination must not be a directory. */
+  if (lstat64 (dest, &stats) == 0)
+    {
+      if (S_ISDIR (stats.st_mode))
+	{
+	  fprintf (stderr, _("%s: destination must not be a directory\n"),
+		   dest);
+	  return 1;
+	}
+      else if (unlink (dest) && errno != ENOENT)
+	{
+	  fprintf (stderr, _("%s: failed to remove the old destination\n"),
+		   dest);
+	  return 1;
+	}
+    }
+  else if (errno != ENOENT)
+    {
+      error = strerror (errno);
+      fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error);
+      return -1;
+    }
+
+  if (symlink (src, dest) == 0)
+    {
+      /* Destination must exist by now. */
+      if (access (dest, F_OK))
+        {
+	  error = strerror (errno);
+	  unlink (dest);
+	  fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
+		   src, dest, error);
+	  return 1;
+	}
+      return 0;
+    }
+  else
+    {
+      error = strerror (errno);
+      fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
+	       src, dest, error);
+      return 1;
+    }
+}
diff --git a/REORG.TODO/elf/sofini.c b/REORG.TODO/elf/sofini.c
new file mode 100644
index 0000000000..13e74b7903
--- /dev/null
+++ b/REORG.TODO/elf/sofini.c
@@ -0,0 +1,19 @@
+/* Finalizer module for ELF shared C library.  This provides terminating
+   null pointer words in the `.ctors' and `.dtors' sections.  */
+
+#ifndef NO_CTORS_DTORS_SECTIONS
+static void (*const __CTOR_END__[1]) (void)
+     __attribute__ ((used, section (".ctors")))
+     = { 0 };
+static void (*const __DTOR_END__[1]) (void)
+     __attribute__ ((used, section (".dtors")))
+     = { 0 };
+#endif
+
+/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
+   this would be the 'length' field in a real FDE.  */
+
+typedef unsigned int ui32 __attribute__ ((mode (SI)));
+static const ui32 __FRAME_END__[1]
+  __attribute__ ((used, section (".eh_frame")))
+  = { 0 };
diff --git a/REORG.TODO/elf/soinit.c b/REORG.TODO/elf/soinit.c
new file mode 100644
index 0000000000..fe9935732b
--- /dev/null
+++ b/REORG.TODO/elf/soinit.c
@@ -0,0 +1,43 @@
+/* Initializer module for building the ELF shared C library.  This file and
+   sofini.c do the work normally done by crtbeginS.o and crtendS.o, to wrap
+   the `.ctors' and `.dtors' sections so the lists are terminated, and
+   calling those lists of functions.  */
+
+#ifndef NO_CTORS_DTORS_SECTIONS
+# include <stdlib.h>
+
+static void (*const __CTOR_LIST__[1]) (void)
+  __attribute__ ((used, section (".ctors")))
+  = { (void (*) (void)) -1 };
+static void (*const __DTOR_LIST__[1]) (void)
+  __attribute__ ((used, section (".dtors")))
+  = { (void (*) (void)) -1 };
+
+static inline void
+run_hooks (void (*const list[]) (void))
+{
+  while (*++list)
+    (**list) ();
+}
+
+/* This function will be called from _init in init-first.c.  */
+void
+__libc_global_ctors (void)
+{
+  /* Call constructor functions.  */
+  run_hooks (__CTOR_LIST__);
+}
+
+
+/* This function becomes the DT_FINI termination function
+   for the C library.  */
+void
+__libc_fini (void)
+{
+  /* Call destructor functions.  */
+  run_hooks (__DTOR_LIST__);
+}
+
+void (*_fini_ptr) (void) __attribute__ ((section (".fini_array")))
+     = &__libc_fini;
+#endif
diff --git a/REORG.TODO/elf/sotruss-lib.c b/REORG.TODO/elf/sotruss-lib.c
new file mode 100644
index 0000000000..da2fedd52a
--- /dev/null
+++ b/REORG.TODO/elf/sotruss-lib.c
@@ -0,0 +1,386 @@
+/* Trace calls through PLTs and show caller, callee, and parameters.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <error.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <ldsodefs.h>
+
+
+extern const char *__progname;
+extern const char *__progname_full;
+
+
+/* List of objects to trace calls from.  */
+static const char *fromlist;
+/* List of objects to trace calls to.  */
+static const char *tolist;
+
+/* If non-zero, also trace returns of the calls.  */
+static int do_exit;
+/* If non-zero print PID for each line.  */
+static int print_pid;
+
+/* The output stream to use.  */
+static FILE *out_file;
+
+
+static int
+match_pid (pid_t pid, const char *which)
+{
+  if (which == NULL || which[0] == '\0')
+    {
+      print_pid = 1;
+      return 1;
+    }
+
+  char *endp;
+  unsigned long n = strtoul (which, &endp, 0);
+  return *endp == '\0' && n == pid;
+}
+
+
+static void
+init (void)
+{
+  fromlist = getenv ("SOTRUSS_FROMLIST");
+  if (fromlist != NULL && fromlist[0] == '\0')
+    fromlist = NULL;
+  tolist = getenv ("SOTRUSS_TOLIST");
+  if (tolist != NULL && tolist[0] == '\0')
+    tolist = NULL;
+  do_exit = (getenv ("SOTRUSS_EXIT") ?: "")[0] != '\0';
+
+  /* Determine whether this process is supposed to be traced and if
+     yes, whether we should print into a file.  */
+  const char *which_process = getenv ("SOTRUSS_WHICH");
+  pid_t pid = getpid ();
+  int out_fd = -1;
+  if (match_pid (pid, which_process))
+    {
+      const char *out_filename = getenv ("SOTRUSS_OUTNAME");
+
+      if (out_filename != NULL && out_filename[0] != 0)
+	{
+	  size_t out_filename_len = strlen (out_filename) + 13;
+	  char fullname[out_filename_len];
+	  char *endp = stpcpy (fullname, out_filename);
+	  if (which_process == NULL || which_process[0] == '\0')
+	    snprintf (endp, 13, ".%ld", (long int) pid);
+
+	  out_fd = open (fullname, O_RDWR | O_CREAT | O_TRUNC, 0666);
+	  if (out_fd != -1)
+	    print_pid = 0;
+	}
+    }
+
+  /* If we do not write into a file write to stderr.  Duplicate the
+     descriptor so that we can keep printing in case the program
+     closes stderr.  Try first to allocate a descriptor with a value
+     usually not used as to minimize interference with the
+     program.  */
+  if (out_fd == -1)
+    {
+      out_fd = fcntl (STDERR_FILENO, F_DUPFD, 1000);
+      if (out_fd == -1)
+	out_fd = dup (STDERR_FILENO);
+    }
+
+  if (out_fd != -1)
+    {
+      /* Convert file descriptor into a stream.  */
+      out_file = fdopen (out_fd, "w");
+      if (out_file != NULL)
+	setlinebuf (out_file);
+    }
+}
+
+
+/* Audit interface verification.  We also initialize everything if
+   everything checks out OK.  */
+unsigned int
+la_version (unsigned int v)
+{
+  if (v != LAV_CURRENT)
+    error (1, 0, "cannot handle interface version %u", v);
+
+  init ();
+
+  return v;
+}
+
+
+/* Check whether a file name is on the colon-separated list of file
+   names.  */
+static unsigned int
+match_file (const char *list, const char *name, size_t name_len,
+	    unsigned int mask)
+{
+  if (list[0] == '\0')
+    return 0;
+
+  const char *cp = list;
+  while (1)
+    {
+      if (strncmp (cp, name, name_len) == 0
+	  && (cp[name_len] == ':' || cp[name_len] == '\0'))
+	return mask;
+
+      cp = strchr (cp, ':');
+      if (cp == NULL)
+	return 0;
+      ++cp;
+    }
+}
+
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  if (out_file == NULL)
+    return 0;
+
+  const char *full_name = map->l_name ?: "";
+  if (full_name[0] == '\0')
+    full_name = __progname_full;
+  size_t full_name_len = strlen (full_name);
+  const char *base_name = basename (full_name);
+  if (base_name[0] == '\0')
+    base_name = __progname;
+  size_t base_name_len = strlen (base_name);
+
+  int result = 0;
+  const char *print_name = NULL;
+  for (struct libname_list *l = map->l_libname; l != NULL; l = l->next)
+    {
+      if (print_name == NULL || (print_name[0] == '/' && l->name[0] != '/'))
+	print_name = l->name;
+
+      if (fromlist != NULL)
+	result |= match_file (fromlist, l->name, strlen (l->name),
+			      LA_FLG_BINDFROM);
+
+      if (tolist != NULL)
+	result |= match_file (tolist, l->name, strlen (l->name),LA_FLG_BINDTO);
+    }
+
+  if (print_name == NULL)
+    print_name = base_name;
+  if (print_name[0] == '\0')
+    print_name = __progname;
+
+  /* We cannot easily get to the object name in the PLT handling
+     functions.  Use the cookie to get the string pointer passed back
+     to us.  */
+  *cookie = (uintptr_t) print_name;
+
+  /* The object name has to be on the list of objects to trace calls
+     from or that list must be empty.  In the latter case we trace
+     only calls from the main binary.  */
+  if (fromlist == NULL)
+    result |= map->l_name[0] == '\0' ? LA_FLG_BINDFROM : 0;
+  else
+    result |= (match_file (fromlist, full_name, full_name_len,
+			   LA_FLG_BINDFROM)
+	       | match_file (fromlist, base_name, base_name_len,
+			     LA_FLG_BINDFROM));
+
+  /* The object name has to be on the list of objects to trace calls
+     to or that list must be empty.  In the latter case we trace
+     calls toall objects.  */
+  if (tolist == NULL)
+    result |= LA_FLG_BINDTO;
+  else
+    result |= (match_file (tolist, full_name, full_name_len, LA_FLG_BINDTO)
+	       | match_file (tolist, base_name, base_name_len, LA_FLG_BINDTO));
+
+  return result;
+}
+
+
+#if __ELF_NATIVE_CLASS == 32
+# define la_symbind la_symbind32
+typedef Elf32_Sym Elf_Sym;
+#else
+# define la_symbind la_symbind64
+typedef Elf64_Sym Elf_Sym;
+#endif
+
+uintptr_t
+la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+	    uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+  if (!do_exit)
+    *flags = LA_SYMB_NOPLTEXIT;
+
+  return sym->st_value;
+}
+
+
+static void
+print_enter (uintptr_t *refcook, uintptr_t *defcook, const char *symname,
+	     unsigned long int reg1, unsigned long int reg2,
+	     unsigned long int reg3, unsigned int flags)
+{
+  char buf[3 * sizeof (pid_t) + 3];
+  buf[0] = '\0';
+  if (print_pid)
+    snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ());
+
+  fprintf (out_file, "%s%15s -> %-15s:%s%s(0x%lx, 0x%lx, 0x%lx)\n",
+	   buf, (char *) *refcook, (char *) *defcook,
+	   (flags & LA_SYMB_NOPLTEXIT) ? "*" : " ", symname, reg1, reg2, reg3);
+}
+
+
+#ifdef __i386__
+Elf32_Addr
+la_i86_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)),
+		     unsigned int ndx __attribute__ ((unused)),
+		     uintptr_t *refcook, uintptr_t *defcook,
+		     La_i86_regs *regs, unsigned int *flags,
+		     const char *symname, long int *framesizep)
+{
+  unsigned long int *sp = (unsigned long int *) regs->lr_esp;
+
+  print_enter (refcook, defcook, symname, sp[1], sp[2], sp[3], *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+#elif defined __x86_64__
+Elf64_Addr
+la_x86_64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)),
+			unsigned int ndx __attribute__ ((unused)),
+			uintptr_t *refcook, uintptr_t *defcook,
+			La_x86_64_regs *regs, unsigned int *flags,
+			const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname,
+	       regs->lr_rdi, regs->lr_rsi, regs->lr_rdx, *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+#elif defined __sparc__ && !defined __arch64__
+Elf32_Addr
+la_sparc32_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)),
+			 unsigned int ndx __attribute__ ((unused)),
+			 uintptr_t *refcook, uintptr_t *defcook,
+			 La_sparc32_regs *regs, unsigned int *flags,
+			 const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname,
+	       regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+	       *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+#elif defined __sparc__ && defined __arch64__
+Elf64_Addr
+la_sparc64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)),
+			 unsigned int ndx __attribute__ ((unused)),
+			 uintptr_t *refcook, uintptr_t *defcook,
+			 La_sparc64_regs *regs, unsigned int *flags,
+			 const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname,
+	       regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+	       *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+#elif !defined HAVE_ARCH_PLTENTER
+# warning "pltenter for architecture not supported"
+#endif
+
+
+static void
+print_exit (uintptr_t *refcook, uintptr_t *defcook, const char *symname,
+	    unsigned long int reg)
+{
+  char buf[3 * sizeof (pid_t) + 3];
+  buf[0] = '\0';
+  if (print_pid)
+    snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ());
+
+  fprintf (out_file, "%s%15s -> %-15s:%s%s - 0x%lx\n",
+	   buf, (char *) *refcook, (char *) *defcook, " ", symname, reg);
+}
+
+
+#ifdef __i386__
+unsigned int
+la_i86_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+		    uintptr_t *defcook, const struct La_i86_regs *inregs,
+		    struct La_i86_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_eax);
+
+  return 0;
+}
+#elif defined __x86_64__
+unsigned int
+la_x86_64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+		       uintptr_t *defcook, const struct La_x86_64_regs *inregs,
+		       struct La_x86_64_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_rax);
+
+  return 0;
+}
+#elif defined __sparc__ && !defined __arch64__
+unsigned int
+la_sparc32_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+			uintptr_t *defcook, const struct La_sparc32_regs *inregs,
+			struct La_sparc32_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_reg[0]);
+
+  return 0;
+}
+#elif defined __sparc__ && defined __arch64__
+unsigned int
+la_sparc64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+			uintptr_t *defcook, const struct La_sparc64_regs *inregs,
+			struct La_sparc64_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_reg[0]);
+
+  return 0;
+}
+#elif !defined HAVE_ARCH_PLTEXIT
+# warning "pltexit for architecture not supported"
+#endif
diff --git a/REORG.TODO/elf/sotruss.sh b/REORG.TODO/elf/sotruss.sh
new file mode 100755
index 0000000000..c83e837e0e
--- /dev/null
+++ b/REORG.TODO/elf/sotruss.sh
@@ -0,0 +1,152 @@
+#! @BASH@
+# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# We should be able to find the translation right at the beginning.
+TEXTDOMAIN=libc
+TEXTDOMAINDIR=@TEXTDOMAINDIR@
+
+unset SOTRUSS_FROMLIST
+unset SOTRUSS_TOLIST
+unset SOTRUSS_OUTNAME
+unset SOTRUSS_EXIT
+unset SOTRUSS_NOINDENT
+SOTRUSS_WHICH=$$
+lib='@PREFIX@/$LIB/audit/sotruss-lib.so'
+
+do_help() {
+  echo $"Usage: sotruss [OPTION...] [--] EXECUTABLE [EXECUTABLE-OPTION...]
+  -F, --from FROMLIST     Trace calls from objects on FROMLIST
+  -T, --to TOLIST         Trace calls to objects on TOLIST
+
+  -e, --exit              Also show exits from the function calls
+  -f, --follow            Trace child processes
+  -o, --output FILENAME   Write output to FILENAME (or FILENAME.$PID in case
+			  -f is also used) instead of standard error
+
+  -?, --help              Give this help list
+      --usage             Give a short usage message
+      --version           Print program version"
+
+  echo
+  printf $"Mandatory arguments to long options are also mandatory for any corresponding\nshort options.\n"
+  echo
+
+  printf $"For bug reporting instructions, please see:\\n%s.\\n" \
+    "@REPORT_BUGS_TO@"
+  exit 0
+}
+
+do_missing_arg() {
+  printf >&2 $"%s: option requires an argument -- '%s'\n" sotruss "$1"
+  printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss
+  exit 1
+}
+
+do_ambiguous() {
+  printf >&2 $"%s: option is ambiguous; possibilities:"
+  while test $# -gt 0; do
+    printf >&2 " '%s'" $1
+    shift
+  done
+  printf >&2 "\n"
+  printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss
+  exit 1
+}
+
+while test $# -gt 0; do
+  case "$1" in
+  --v | --ve | --ver | --vers | --versi | --versio | --version)
+    echo "sotruss @PKGVERSION@@VERSION@"
+    printf $"Copyright (C) %s Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+" "2017"
+    printf $"Written by %s.\n" "Ulrich Drepper"
+    exit 0
+    ;;
+  -\? | --h | --he | --hel | --help)
+    do_help
+    ;;
+  --u | --us | --usa | --usag | --usage)
+    printf $"Usage: %s [-ef] [-F FROMLIST] [-o FILENAME] [-T TOLIST] [--exit]
+	    [--follow] [--from FROMLIST] [--output FILENAME] [--to TOLIST]
+	    [--help] [--usage] [--version] [--]
+	    EXECUTABLE [EXECUTABLE-OPTION...]\n" sotruss
+    exit 0
+    ;;
+  -F | --fr | --fro | --from)
+    if test $# -eq 1; then
+      do_missing_arg "$1"
+    fi
+    shift
+    SOTRUSS_FROMLIST="$1"
+    ;;
+  -T | --t | --to)
+    if test $# -eq 1; then
+      do_missing_arg "$1"
+    fi
+    shift
+    SOTRUSS_TOLIST="$1"
+    ;;
+  -o | --o | --ou | --out | --outp | --outpu | --output)
+    if test $# -eq 1; then
+      do_missing_arg "$1"
+    fi
+    shift
+    SOTRUSS_OUTNAME="$1"
+    ;;
+  -f | --fo | --fol | --foll | --follo | --follow)
+    unset SOTRUSS_WHICH
+    ;;
+  -l | --l | --li | --lib)
+    if test $# -eq 1; then
+      do_missing_arg "$1"
+    fi
+    shift
+    lib="$1"
+    ;;
+  -e | --e | --ex | --exi | --exit)
+    SOTRUSS_EXIT=1
+    ;;
+  --f)
+    do_ambiguous '--from' '--follow'
+    ;;
+  --)
+    shift
+    break
+    ;;
+  -*)
+    printf >&2 $"%s: unrecognized option '%c%s'\n" sotruss '-' ${1#-}
+    printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss
+    exit 1
+    ;;
+  *)
+    break
+    ;;
+  esac
+  shift
+done
+
+export SOTRUSS_FROMLIST
+export SOTRUSS_TOLIST
+export SOTRUSS_OUTNAME
+export SOTRUSS_WHICH
+export SOTRUSS_EXIT
+export LD_AUDIT="$lib"
+
+exec "$@"
diff --git a/REORG.TODO/elf/sprof.c b/REORG.TODO/elf/sprof.c
new file mode 100644
index 0000000000..85c4975360
--- /dev/null
+++ b/REORG.TODO/elf/sprof.c
@@ -0,0 +1,1436 @@
+/* Read and display shared object profiling data.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <argp.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <error.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libintl.h>
+#include <locale.h>
+#include <obstack.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <ldsodefs.h>
+#include <sys/gmon.h>
+#include <sys/gmon_out.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+/* Get libc version number.  */
+#include "../version.h"
+
+#define PACKAGE _libc_intl_domainname
+
+
+#include <endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+# define byteorder ELFDATA2MSB
+# define byteorder_name "big-endian"
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# define byteorder ELFDATA2LSB
+# define byteorder_name "little-endian"
+#else
+# error "Unknown BYTE_ORDER " BYTE_ORDER
+# define byteorder ELFDATANONE
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+
+
+extern int __profile_frequency (void);
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+#define OPT_TEST	1
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Output selection:") },
+  { "call-pairs", 'c', NULL, 0,
+    N_("print list of count paths and their number of use") },
+  { "flat-profile", 'p', NULL, 0,
+    N_("generate flat profile with counts and ticks") },
+  { "graph", 'q', NULL, 0, N_("generate call graph") },
+
+  { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
+  { NULL, 0, NULL, 0, NULL }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Read and display shared object profiling data.");
+//For bug reporting instructions, please see:\n
+//<http://www.gnu.org/software/libc/bugs.html>.\n");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("SHOBJ [PROFDATA]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, more_help
+};
+
+
+/* Operation modes.  */
+static enum
+{
+  NONE = 0,
+  FLAT_MODE = 1 << 0,
+  CALL_GRAPH_MODE = 1 << 1,
+  CALL_PAIRS = 1 << 2,
+
+  DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE
+} mode;
+
+/* Nozero for testing.  */
+static int do_test;
+
+/* Strcuture describing calls.  */
+struct here_fromstruct
+{
+  struct here_cg_arc_record volatile *here;
+  uint16_t link;
+};
+
+/* We define a special type to address the elements of the arc table.
+   This is basically the `gmon_cg_arc_record' format but it includes
+   the room for the tag and it uses real types.  */
+struct here_cg_arc_record
+{
+  uintptr_t from_pc;
+  uintptr_t self_pc;
+  uint32_t count;
+} __attribute__ ((packed));
+
+
+struct known_symbol;
+struct arc_list
+{
+  size_t idx;
+  uintmax_t count;
+
+  struct arc_list *next;
+};
+
+static struct obstack ob_list;
+
+
+struct known_symbol
+{
+  const char *name;
+  uintptr_t addr;
+  size_t size;
+  bool weak;
+  bool hidden;
+
+  uintmax_t ticks;
+  uintmax_t calls;
+
+  struct arc_list *froms;
+  struct arc_list *tos;
+};
+
+
+struct shobj
+{
+  const char *name;		/* User-provided name.  */
+
+  struct link_map *map;
+  const char *dynstrtab;	/* Dynamic string table of shared object.  */
+  const char *soname;		/* Soname of shared object.  */
+
+  uintptr_t lowpc;
+  uintptr_t highpc;
+  unsigned long int kcountsize;
+  size_t expected_size;		/* Expected size of profiling file.  */
+  size_t tossize;
+  size_t fromssize;
+  size_t fromlimit;
+  unsigned int hashfraction;
+  int s_scale;
+
+  void *symbol_map;
+  size_t symbol_mapsize;
+  const ElfW(Sym) *symtab;
+  size_t symtab_size;
+  const char *strtab;
+
+  struct obstack ob_str;
+  struct obstack ob_sym;
+};
+
+
+struct real_gmon_hist_hdr
+{
+  char *low_pc;
+  char *high_pc;
+  int32_t hist_size;
+  int32_t prof_rate;
+  char dimen[15];
+  char dimen_abbrev;
+};
+
+
+struct profdata
+{
+  void *addr;
+  off_t size;
+
+  char *hist;
+  struct real_gmon_hist_hdr *hist_hdr;
+  uint16_t *kcount;
+  uint32_t narcs;		/* Number of arcs in toset.  */
+  struct here_cg_arc_record *data;
+  uint16_t *tos;
+  struct here_fromstruct *froms;
+};
+
+/* Search tree for symbols.  */
+static void *symroot;
+static struct known_symbol **sortsym;
+static size_t symidx;
+static uintmax_t total_ticks;
+
+/* Prototypes for local functions.  */
+static struct shobj *load_shobj (const char *name);
+static void unload_shobj (struct shobj *shobj);
+static struct profdata *load_profdata (const char *name, struct shobj *shobj);
+static void unload_profdata (struct profdata *profdata);
+static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
+static void count_calls (struct shobj *shobj, struct profdata *profdata);
+static void read_symbols (struct shobj *shobj);
+static void add_arcs (struct profdata *profdata);
+static void generate_flat_profile (struct profdata *profdata);
+static void generate_call_graph (struct profdata *profdata);
+static void generate_call_pair_list (struct profdata *profdata);
+
+
+int
+main (int argc, char *argv[])
+{
+  const char *shobj;
+  const char *profdata;
+  struct shobj *shobj_handle;
+  struct profdata *profdata_handle;
+  int remaining;
+
+  setlocale (LC_ALL, "");
+
+  /* Initialize the message catalog.  */
+  textdomain (_libc_intl_domainname);
+
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  if (argc - remaining == 0 || argc - remaining > 2)
+    {
+      /* We need exactly two non-option parameter.  */
+      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+		 program_invocation_short_name);
+      exit (1);
+    }
+
+  /* Get parameters.  */
+  shobj = argv[remaining];
+  if (argc - remaining == 2)
+    profdata = argv[remaining + 1];
+  else
+    /* No filename for the profiling data given.  We will determine it
+       from the soname of the shobj, later.  */
+    profdata = NULL;
+
+  /* First see whether we can load the shared object.  */
+  shobj_handle = load_shobj (shobj);
+  if (shobj_handle == NULL)
+    exit (1);
+
+  /* We can now determine the filename for the profiling data, if
+     nececessary.  */
+  if (profdata == NULL)
+    {
+      char *newp;
+      const char *soname;
+      size_t soname_len;
+
+      soname = shobj_handle->soname ?: basename (shobj);
+      soname_len = strlen (soname);
+      newp = (char *) alloca (soname_len + sizeof ".profile");
+      stpcpy (mempcpy (newp, soname, soname_len), ".profile");
+      profdata = newp;
+    }
+
+  /* Now see whether the profiling data file matches the given object.   */
+  profdata_handle = load_profdata (profdata, shobj_handle);
+  if (profdata_handle == NULL)
+    {
+      unload_shobj (shobj_handle);
+
+      exit (1);
+    }
+
+  read_symbols (shobj_handle);
+
+  /* Count the ticks.  */
+  count_total_ticks (shobj_handle, profdata_handle);
+
+  /* Count the calls.  */
+  count_calls (shobj_handle, profdata_handle);
+
+  /* Add the arc information.  */
+  add_arcs (profdata_handle);
+
+  /* If no mode is specified fall back to the default mode.  */
+  if (mode == NONE)
+    mode = DEFAULT_MODE;
+
+  /* Do some work.  */
+  if (mode & FLAT_MODE)
+    generate_flat_profile (profdata_handle);
+
+  if (mode & CALL_GRAPH_MODE)
+    generate_call_graph (profdata_handle);
+
+  if (mode & CALL_PAIRS)
+    generate_call_pair_list (profdata_handle);
+
+  /* Free the resources.  */
+  unload_shobj (shobj_handle);
+  unload_profdata (profdata_handle);
+
+  return 0;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'c':
+      mode |= CALL_PAIRS;
+      break;
+    case 'p':
+      mode |= FLAT_MODE;
+      break;
+    case 'q':
+      mode |= CALL_GRAPH_MODE;
+      break;
+    case OPT_TEST:
+      do_test = 1;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+static char *
+more_help (int key, const char *text, void *input)
+{
+  char *tp = NULL;
+  switch (key)
+    {
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      if (asprintf (&tp, gettext ("\
+For bug reporting instructions, please see:\n\
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
+    default:
+      break;
+    }
+  return (char *) text;
+}
+
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "sprof %s%s\n", PKGVERSION, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"),
+	   "2017");
+  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
+}
+
+
+/* Note that we must not use `dlopen' etc.  The shobj object must not
+   be loaded for use.  */
+static struct shobj *
+load_shobj (const char *name)
+{
+  struct link_map *map = NULL;
+  struct shobj *result;
+  ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
+  ElfW(Addr) mapend = 0;
+  const ElfW(Phdr) *ph;
+  size_t textsize;
+  ElfW(Ehdr) *ehdr;
+  int fd;
+  ElfW(Shdr) *shdr;
+  size_t pagesize = getpagesize ();
+
+  /* Since we use dlopen() we must be prepared to work around the sometimes
+     strange lookup rules for the shared objects.  If we have a file foo.so
+     in the current directory and the user specfies foo.so on the command
+     line (without specifying a directory) we should load the file in the
+     current directory even if a normal dlopen() call would read the other
+     file.  We do this by adding a directory portion to the name.  */
+  if (strchr (name, '/') == NULL)
+    {
+      char *load_name = (char *) alloca (strlen (name) + 3);
+      stpcpy (stpcpy (load_name, "./"), name);
+
+      map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF);
+    }
+  if (map == NULL)
+    {
+      map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF);
+      if (map == NULL)
+	{
+	  error (0, errno, _("failed to load shared object `%s'"), name);
+	  return NULL;
+	}
+    }
+
+  /* Prepare the result.  */
+  result = (struct shobj *) calloc (1, sizeof (struct shobj));
+  if (result == NULL)
+    {
+      error (0, errno, _("cannot create internal descriptor"));
+      dlclose (map);
+      return NULL;
+    }
+  result->name = name;
+  result->map = map;
+
+  /* Compute the size of the sections which contain program code.
+     This must match the code in dl-profile.c (_dl_start_profile).  */
+  for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
+    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
+      {
+	ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
+	ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
+			  & ~(pagesize - 1));
+
+	if (start < mapstart)
+	  mapstart = start;
+	if (end > mapend)
+	  mapend = end;
+      }
+
+  result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
+			     HISTFRACTION * sizeof (HISTCOUNTER));
+  result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
+			    HISTFRACTION * sizeof (HISTCOUNTER));
+  if (do_test)
+    printf ("load addr: %0#*" PRIxPTR "\n"
+	    "lower bound PC: %0#*" PRIxPTR "\n"
+	    "upper bound PC: %0#*" PRIxPTR "\n",
+	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
+	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
+	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
+
+  textsize = result->highpc - result->lowpc;
+  result->kcountsize = textsize / HISTFRACTION;
+  result->hashfraction = HASHFRACTION;
+  if (do_test)
+    printf ("hashfraction = %d\ndivider = %Zu\n",
+	    result->hashfraction,
+	    result->hashfraction * sizeof (struct here_fromstruct));
+  result->tossize = textsize / HASHFRACTION;
+  result->fromlimit = textsize * ARCDENSITY / 100;
+  if (result->fromlimit < MINARCS)
+    result->fromlimit = MINARCS;
+  if (result->fromlimit > MAXARCS)
+    result->fromlimit = MAXARCS;
+  result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
+
+  result->expected_size = (sizeof (struct gmon_hdr)
+			   + 4 + sizeof (struct gmon_hist_hdr)
+			   + result->kcountsize
+			   + 4 + 4
+			   + (result->fromssize
+			      * sizeof (struct here_cg_arc_record)));
+
+  if (do_test)
+    printf ("expected size: %Zd\n", result->expected_size);
+
+#define SCALE_1_TO_1	0x10000L
+
+  if (result->kcountsize < result->highpc - result->lowpc)
+    {
+      size_t range = result->highpc - result->lowpc;
+      size_t quot = range / result->kcountsize;
+
+      if (quot >= SCALE_1_TO_1)
+	result->s_scale = 1;
+      else if (quot >= SCALE_1_TO_1 / 256)
+	result->s_scale = SCALE_1_TO_1 / quot;
+      else if (range > ULONG_MAX / 256)
+	result->s_scale = ((SCALE_1_TO_1 * 256)
+			   / (range / (result->kcountsize / 256)));
+      else
+	result->s_scale = ((SCALE_1_TO_1 * 256)
+			   / ((range * 256) / result->kcountsize));
+    }
+  else
+    result->s_scale = SCALE_1_TO_1;
+
+  if (do_test)
+    printf ("s_scale: %d\n", result->s_scale);
+
+  /* Determine the dynamic string table.  */
+  if (map->l_info[DT_STRTAB] == NULL)
+    result->dynstrtab = NULL;
+  else
+    result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
+  if (do_test)
+    printf ("string table: %p\n", result->dynstrtab);
+
+  /* Determine the soname.  */
+  if (map->l_info[DT_SONAME] == NULL)
+    result->soname = NULL;
+  else
+    result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
+  if (do_test && result->soname != NULL)
+    printf ("soname: %s\n", result->soname);
+
+  /* Now we have to load the symbol table.
+
+     First load the section header table.  */
+  ehdr = (ElfW(Ehdr) *) map->l_map_start;
+
+  /* Make sure we are on the right party.  */
+  if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
+    abort ();
+
+  /* And we need the shared object file descriptor again.  */
+  fd = open (map->l_name, O_RDONLY);
+  if (fd == -1)
+    /* Dooh, this really shouldn't happen.  We know the file is available.  */
+    error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
+	   map->l_name);
+
+  /* Map the section header.  */
+  size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
+  shdr = (ElfW(Shdr) *) alloca (size);
+  if (pread (fd, shdr, size, ehdr->e_shoff) != size)
+    error (EXIT_FAILURE, errno, _("reading of section headers failed"));
+
+  /* Get the section header string table.  */
+  char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
+  if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
+	     shdr[ehdr->e_shstrndx].sh_offset)
+      != shdr[ehdr->e_shstrndx].sh_size)
+    error (EXIT_FAILURE, errno,
+	   _("reading of section header string table failed"));
+
+  /* Search for the ".symtab" section.  */
+  ElfW(Shdr) *symtab_entry = NULL;
+  ElfW(Shdr) *debuglink_entry = NULL;
+  for (int idx = 0; idx < ehdr->e_shnum; ++idx)
+    if (shdr[idx].sh_type == SHT_SYMTAB
+	&& strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
+      {
+	symtab_entry = &shdr[idx];
+	break;
+      }
+    else if (shdr[idx].sh_type == SHT_PROGBITS
+	     && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0)
+      debuglink_entry = &shdr[idx];
+
+  /* Get the file name of the debuginfo file if necessary.  */
+  int symfd = fd;
+  if (symtab_entry == NULL && debuglink_entry != NULL)
+    {
+      size_t size = debuglink_entry->sh_size;
+      char *debuginfo_fname = (char *) alloca (size + 1);
+      debuginfo_fname[size] = '\0';
+      if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
+	  != size)
+	{
+	  fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n"));
+	  goto no_debuginfo;
+	}
+
+      static const char procpath[] = "/proc/self/fd/%d";
+      char origprocname[sizeof (procpath) + sizeof (int) * 3];
+      snprintf (origprocname, sizeof (origprocname), procpath, fd);
+      char *origlink = (char *) alloca (PATH_MAX);
+      ssize_t n = readlink (origprocname, origlink, PATH_MAX - 1);
+      if (n == -1)
+	goto no_debuginfo;
+      origlink[n] = '\0';
+
+      /* Try to find the actual file.  There are three places:
+	 1. the same directory the DSO is in
+	 2. in a subdir named .debug of the directory the DSO is in
+	 3. in /usr/lib/debug/PATH-OF-DSO
+      */
+      char *realname = canonicalize_file_name (origlink);
+      char *cp = NULL;
+      if (realname == NULL || (cp = strrchr (realname, '/')) == NULL)
+	error (EXIT_FAILURE, errno, _("cannot determine file name"));
+
+      /* Leave the last slash in place.  */
+      *++cp = '\0';
+
+      /* First add the debuginfo file name only.  */
+      static const char usrlibdebug[]= "/usr/lib/debug/";
+      char *workbuf = (char *) alloca (sizeof (usrlibdebug)
+				       + (cp - realname)
+				       + strlen (debuginfo_fname));
+      strcpy (stpcpy (workbuf, realname), debuginfo_fname);
+
+      int fd2 = open (workbuf, O_RDONLY);
+      if (fd2 == -1)
+	{
+	  strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"),
+		  debuginfo_fname);
+	  fd2 = open (workbuf, O_RDONLY);
+	  if (fd2 == -1)
+	    {
+	      strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname),
+		      debuginfo_fname);
+	      fd2 = open (workbuf, O_RDONLY);
+	    }
+	}
+
+      if (fd2 != -1)
+	{
+	  ElfW(Ehdr) ehdr2;
+
+	  /* Read the ELF header.  */
+	  if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
+	    error (EXIT_FAILURE, errno,
+		   _("reading of ELF header failed"));
+
+	  /* Map the section header.  */
+	  size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
+	  ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
+	  if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
+	    error (EXIT_FAILURE, errno,
+		   _("reading of section headers failed"));
+
+	  /* Get the section header string table.  */
+	  shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
+	  if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
+		     shdr2[ehdr2.e_shstrndx].sh_offset)
+	      != shdr2[ehdr2.e_shstrndx].sh_size)
+	    error (EXIT_FAILURE, errno,
+		   _("reading of section header string table failed"));
+
+	  /* Search for the ".symtab" section.  */
+	  for (int idx = 0; idx < ehdr2.e_shnum; ++idx)
+	    if (shdr2[idx].sh_type == SHT_SYMTAB
+		&& strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0)
+	      {
+		symtab_entry = &shdr2[idx];
+		shdr = shdr2;
+		symfd = fd2;
+		break;
+	      }
+
+	  if  (fd2 != symfd)
+	    close (fd2);
+	}
+    }
+
+ no_debuginfo:
+  if (symtab_entry == NULL)
+    {
+      fprintf (stderr, _("\
+*** The file `%s' is stripped: no detailed analysis possible\n"),
+	      name);
+      result->symtab = NULL;
+      result->strtab = NULL;
+    }
+  else
+    {
+      ElfW(Off) min_offset, max_offset;
+      ElfW(Shdr) *strtab_entry;
+
+      strtab_entry = &shdr[symtab_entry->sh_link];
+
+      /* Find the minimum and maximum offsets that include both the symbol
+	 table and the string table.  */
+      if (symtab_entry->sh_offset < strtab_entry->sh_offset)
+	{
+	  min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
+	  max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
+	}
+      else
+	{
+	  min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
+	  max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
+	}
+
+      result->symbol_map = mmap (NULL, max_offset - min_offset,
+				 PROT_READ, MAP_SHARED|MAP_FILE, symfd,
+				 min_offset);
+      if (result->symbol_map == MAP_FAILED)
+	error (EXIT_FAILURE, errno, _("failed to load symbol data"));
+
+      result->symtab
+	= (const ElfW(Sym) *) ((const char *) result->symbol_map
+			       + (symtab_entry->sh_offset - min_offset));
+      result->symtab_size = symtab_entry->sh_size;
+      result->strtab = ((const char *) result->symbol_map
+			+ (strtab_entry->sh_offset - min_offset));
+      result->symbol_mapsize = max_offset - min_offset;
+    }
+
+  /* Free the descriptor for the shared object.  */
+  close (fd);
+  if (symfd != fd)
+    close (symfd);
+
+  return result;
+}
+
+
+static void
+unload_shobj (struct shobj *shobj)
+{
+  munmap (shobj->symbol_map, shobj->symbol_mapsize);
+  dlclose (shobj->map);
+}
+
+
+static struct profdata *
+load_profdata (const char *name, struct shobj *shobj)
+{
+  struct profdata *result;
+  int fd;
+  struct stat64 st;
+  void *addr;
+  uint32_t *narcsp;
+  size_t fromlimit;
+  struct here_cg_arc_record *data;
+  struct here_fromstruct *froms;
+  uint16_t *tos;
+  size_t fromidx;
+  size_t idx;
+
+  fd = open (name, O_RDONLY);
+  if (fd == -1)
+    {
+      char *ext_name;
+
+      if (errno != ENOENT || strchr (name, '/') != NULL)
+	/* The file exists but we are not allowed to read it or the
+	   file does not exist and the name includes a path
+	   specification..  */
+	return NULL;
+
+      /* A file with the given name does not exist in the current
+	 directory, try it in the default location where the profiling
+	 files are created.  */
+      ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
+      stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
+      name = ext_name;
+
+      fd = open (ext_name, O_RDONLY);
+      if (fd == -1)
+	{
+	  /* Even this file does not exist.  */
+	  error (0, errno, _("cannot load profiling data"));
+	  return NULL;
+	}
+    }
+
+  /* We have found the file, now make sure it is the right one for the
+     data file.  */
+  if (fstat64 (fd, &st) < 0)
+    {
+      error (0, errno, _("while stat'ing profiling data file"));
+      close (fd);
+      return NULL;
+    }
+
+  if ((size_t) st.st_size != shobj->expected_size)
+    {
+      error (0, 0,
+	     _("profiling data file `%s' does not match shared object `%s'"),
+	     name, shobj->name);
+      close (fd);
+      return NULL;
+    }
+
+  /* The data file is most probably the right one for our shared
+     object.  Map it now.  */
+  addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
+  if (addr == MAP_FAILED)
+    {
+      error (0, errno, _("failed to mmap the profiling data file"));
+      close (fd);
+      return NULL;
+    }
+
+  /* We don't need the file desriptor anymore.  */
+  if (close (fd) < 0)
+    {
+      error (0, errno, _("error while closing the profiling data file"));
+      munmap (addr, st.st_size);
+      return NULL;
+    }
+
+  /* Prepare the result.  */
+  result = (struct profdata *) calloc (1, sizeof (struct profdata));
+  if (result == NULL)
+    {
+      error (0, errno, _("cannot create internal descriptor"));
+      munmap (addr, st.st_size);
+      return NULL;
+    }
+
+  /* Store the address and size so that we can later free the resources.  */
+  result->addr = addr;
+  result->size = st.st_size;
+
+  /* Pointer to data after the header.  */
+  result->hist = (char *) ((struct gmon_hdr *) addr + 1);
+  result->hist_hdr = (struct real_gmon_hist_hdr *) ((char *) result->hist
+						    + sizeof (uint32_t));
+  result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
+				 + sizeof (struct real_gmon_hist_hdr));
+
+  /* Compute pointer to array of the arc information.  */
+  narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
+			 + sizeof (uint32_t));
+  result->narcs = *narcsp;
+  result->data = (struct here_cg_arc_record *) ((char *) narcsp
+						+ sizeof (uint32_t));
+
+  /* Create the gmon_hdr we expect or write.  */
+  struct real_gmon_hdr
+  {
+    char cookie[4];
+    int32_t version;
+    char spare[3 * 4];
+  } gmon_hdr;
+  if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr)
+      || (offsetof (struct real_gmon_hdr, cookie)
+	  != offsetof (struct gmon_hdr, cookie))
+      || (offsetof (struct real_gmon_hdr, version)
+	  != offsetof (struct gmon_hdr, version)))
+    abort ();
+
+  memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
+  gmon_hdr.version = GMON_SHOBJ_VERSION;
+  memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare));
+
+  /* Create the hist_hdr we expect or write.  */
+  struct real_gmon_hist_hdr hist_hdr;
+  if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr)
+      || (offsetof (struct real_gmon_hist_hdr, low_pc)
+	  != offsetof (struct gmon_hist_hdr, low_pc))
+      || (offsetof (struct real_gmon_hist_hdr, high_pc)
+	  != offsetof (struct gmon_hist_hdr, high_pc))
+      || (offsetof (struct real_gmon_hist_hdr, hist_size)
+	  != offsetof (struct gmon_hist_hdr, hist_size))
+      || (offsetof (struct real_gmon_hist_hdr, prof_rate)
+	  != offsetof (struct gmon_hist_hdr, prof_rate))
+      || (offsetof (struct real_gmon_hist_hdr, dimen)
+	  != offsetof (struct gmon_hist_hdr, dimen))
+      || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev)
+	  != offsetof (struct gmon_hist_hdr, dimen_abbrev)))
+    abort ();
+
+  hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
+  hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
+  if (do_test)
+    printf ("low_pc = %p\nhigh_pc = %p\n", hist_hdr.low_pc, hist_hdr.high_pc);
+  hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
+  hist_hdr.prof_rate = __profile_frequency ();
+  strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
+  hist_hdr.dimen_abbrev = 's';
+
+  /* Test whether the header of the profiling data is ok.  */
+  if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
+      || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
+      || memcmp (result->hist_hdr, &hist_hdr,
+		 sizeof (struct gmon_hist_hdr)) != 0
+      || narcsp[-1] != GMON_TAG_CG_ARC)
+    {
+      error (0, 0, _("`%s' is no correct profile data file for `%s'"),
+	     name, shobj->name);
+      if (do_test)
+	{
+	  if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
+	    puts ("gmon_hdr differs");
+	  if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
+	    puts ("result->hist differs");
+	  if (memcmp (result->hist_hdr, &hist_hdr,
+		      sizeof (struct gmon_hist_hdr)) != 0)
+	    puts ("hist_hdr differs");
+	  if (narcsp[-1] != GMON_TAG_CG_ARC)
+	    puts ("narcsp[-1] differs");
+	}
+      free (result);
+      munmap (addr, st.st_size);
+      return NULL;
+    }
+
+  /* We are pretty sure now that this is a correct input file.  Set up
+     the remaining information in the result structure and return.  */
+  result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
+  if (result->tos == NULL)
+    {
+      error (0, errno, _("cannot create internal descriptor"));
+      munmap (addr, st.st_size);
+      free (result);
+      return NULL;
+    }
+
+  result->froms = (struct here_fromstruct *) ((char *) result->tos
+					      + shobj->tossize);
+  fromidx = 0;
+
+  /* Now we have to process all the arc count entries.  */
+  fromlimit = shobj->fromlimit;
+  data = result->data;
+  froms = result->froms;
+  tos = result->tos;
+  for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
+    {
+      size_t to_index;
+      size_t newfromidx;
+      to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
+      newfromidx = fromidx++;
+      froms[newfromidx].here = &data[idx];
+      froms[newfromidx].link = tos[to_index];
+      tos[to_index] = newfromidx;
+    }
+
+  return result;
+}
+
+
+static void
+unload_profdata (struct profdata *profdata)
+{
+  free (profdata->tos);
+  munmap (profdata->addr, profdata->size);
+  free (profdata);
+}
+
+
+static void
+count_total_ticks (struct shobj *shobj, struct profdata *profdata)
+{
+  volatile uint16_t *kcount = profdata->kcount;
+  size_t maxkidx = shobj->kcountsize;
+  size_t factor = 2 * (65536 / shobj->s_scale);
+  size_t kidx = 0;
+  size_t sidx = 0;
+
+  while (sidx < symidx)
+    {
+      uintptr_t start = sortsym[sidx]->addr;
+      uintptr_t end = start + sortsym[sidx]->size;
+
+      while (kidx < maxkidx && factor * kidx < start)
+	++kidx;
+      if (kidx == maxkidx)
+	break;
+
+      while (kidx < maxkidx && factor * kidx < end)
+	sortsym[sidx]->ticks += kcount[kidx++];
+      if (kidx == maxkidx)
+	break;
+
+      total_ticks += sortsym[sidx++]->ticks;
+    }
+}
+
+
+static size_t
+find_symbol (uintptr_t addr)
+{
+  size_t sidx = 0;
+
+  while (sidx < symidx)
+    {
+      uintptr_t start = sortsym[sidx]->addr;
+      uintptr_t end = start + sortsym[sidx]->size;
+
+      if (addr >= start && addr < end)
+	return sidx;
+
+      if (addr < start)
+	break;
+
+      ++sidx;
+    }
+
+  return (size_t) -1l;
+}
+
+
+static void
+count_calls (struct shobj *shobj, struct profdata *profdata)
+{
+  struct here_cg_arc_record *data = profdata->data;
+  uint32_t narcs = profdata->narcs;
+  uint32_t cnt;
+
+  for (cnt = 0; cnt < narcs; ++cnt)
+    {
+      uintptr_t here = data[cnt].self_pc;
+      size_t symbol_idx;
+
+      /* Find the symbol for this address.  */
+      symbol_idx = find_symbol (here);
+      if (symbol_idx != (size_t) -1l)
+	sortsym[symbol_idx]->calls += data[cnt].count;
+    }
+}
+
+
+static int
+symorder (const void *o1, const void *o2)
+{
+  const struct known_symbol *p1 = (const struct known_symbol *) o1;
+  const struct known_symbol *p2 = (const struct known_symbol *) o2;
+
+  return p1->addr - p2->addr;
+}
+
+
+static void
+printsym (const void *node, VISIT value, int level)
+{
+  if (value == leaf || value == postorder)
+    sortsym[symidx++] = *(struct known_symbol **) node;
+}
+
+
+static void
+read_symbols (struct shobj *shobj)
+{
+  int n = 0;
+
+  /* Initialize the obstacks.  */
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+  obstack_init (&shobj->ob_str);
+  obstack_init (&shobj->ob_sym);
+  obstack_init (&ob_list);
+
+  /* Process the symbols.  */
+  if (shobj->symtab != NULL)
+    {
+      const ElfW(Sym) *sym = shobj->symtab;
+      const ElfW(Sym) *sym_end
+	= (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
+      for (; sym < sym_end; sym++)
+	if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
+	     || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
+	    && sym->st_size != 0)
+	  {
+	    struct known_symbol **existp;
+	    struct known_symbol *newsym
+	      = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
+						       sizeof (*newsym));
+	    if (newsym == NULL)
+	      error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
+
+	    newsym->name = &shobj->strtab[sym->st_name];
+	    newsym->addr = sym->st_value;
+	    newsym->size = sym->st_size;
+	    newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK;
+	    newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other)
+			      != STV_DEFAULT);
+	    newsym->ticks = 0;
+	    newsym->calls = 0;
+
+	    existp = tfind (newsym, &symroot, symorder);
+	    if (existp == NULL)
+	      {
+		/* New function.  */
+		tsearch (newsym, &symroot, symorder);
+		++n;
+	      }
+	    else
+	      {
+		/* The function is already defined.  See whether we have
+		   a better name here.  */
+		if (((*existp)->hidden && !newsym->hidden)
+		    || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
+		    || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
+			&& ((*existp)->weak && !newsym->weak)))
+		  *existp = newsym;
+		else
+		  /* We don't need the allocated memory.  */
+		  obstack_free (&shobj->ob_sym, newsym);
+	      }
+	  }
+    }
+  else
+    {
+      /* Blarg, the binary is stripped.  We have to rely on the
+	 information contained in the dynamic section of the object.  */
+      const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map,
+						     l_info[DT_SYMTAB]);
+      const char *strtab = (const char *) D_PTR (shobj->map,
+						 l_info[DT_STRTAB]);
+
+      /* We assume that the string table follows the symbol table,
+	 because there is no way in ELF to know the size of the
+	 dynamic symbol table without looking at the section headers.  */
+      while ((void *) symtab < (void *) strtab)
+	{
+	  if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
+	       || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
+	      && symtab->st_size != 0)
+	    {
+	      struct known_symbol *newsym;
+	      struct known_symbol **existp;
+
+	      newsym =
+		(struct known_symbol *) obstack_alloc (&shobj->ob_sym,
+						       sizeof (*newsym));
+	      if (newsym == NULL)
+		error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
+
+	      newsym->name = &strtab[symtab->st_name];
+	      newsym->addr = symtab->st_value;
+	      newsym->size = symtab->st_size;
+	      newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK;
+	      newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other)
+				!= STV_DEFAULT);
+	      newsym->ticks = 0;
+	      newsym->froms = NULL;
+	      newsym->tos = NULL;
+
+	      existp = tfind (newsym, &symroot, symorder);
+	      if (existp == NULL)
+		{
+		  /* New function.  */
+		  tsearch (newsym, &symroot, symorder);
+		  ++n;
+		}
+	      else
+		{
+		  /* The function is already defined.  See whether we have
+		     a better name here.  */
+		  if (((*existp)->hidden && !newsym->hidden)
+		      || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
+		      || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
+			  && ((*existp)->weak && !newsym->weak)))
+		    *existp = newsym;
+		  else
+		    /* We don't need the allocated memory.  */
+		    obstack_free (&shobj->ob_sym, newsym);
+		}
+	    }
+
+	  ++symtab;
+	}
+    }
+
+  sortsym = malloc (n * sizeof (struct known_symbol *));
+  if (sortsym == NULL)
+    abort ();
+
+  twalk (symroot, printsym);
+}
+
+
+static void
+add_arcs (struct profdata *profdata)
+{
+  uint32_t narcs = profdata->narcs;
+  struct here_cg_arc_record *data = profdata->data;
+  uint32_t cnt;
+
+  for (cnt = 0; cnt < narcs; ++cnt)
+    {
+      /* First add the incoming arc.  */
+      size_t sym_idx = find_symbol (data[cnt].self_pc);
+
+      if (sym_idx != (size_t) -1l)
+	{
+	  struct known_symbol *sym = sortsym[sym_idx];
+	  struct arc_list *runp = sym->froms;
+
+	  while (runp != NULL
+		 && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
+		     || (data[cnt].from_pc != 0
+			 && (runp->idx == (size_t) -1l
+			     || data[cnt].from_pc < sortsym[runp->idx]->addr
+			     || (data[cnt].from_pc
+				 >= (sortsym[runp->idx]->addr
+				     + sortsym[runp->idx]->size))))))
+	    runp = runp->next;
+
+	  if (runp == NULL)
+	    {
+	      /* We need a new entry.  */
+	      struct arc_list *newp = (struct arc_list *)
+		obstack_alloc (&ob_list, sizeof (struct arc_list));
+
+	      if (data[cnt].from_pc == 0)
+		newp->idx = (size_t) -1l;
+	      else
+		newp->idx = find_symbol (data[cnt].from_pc);
+	      newp->count = data[cnt].count;
+	      newp->next = sym->froms;
+	      sym->froms = newp;
+	    }
+	  else
+	    /* Increment the counter for the found entry.  */
+	    runp->count += data[cnt].count;
+	}
+
+      /* Now add it to the appropriate outgoing list.  */
+      sym_idx = find_symbol (data[cnt].from_pc);
+      if (sym_idx != (size_t) -1l)
+	{
+	  struct known_symbol *sym = sortsym[sym_idx];
+	  struct arc_list *runp = sym->tos;
+
+	  while (runp != NULL
+		 && (runp->idx == (size_t) -1l
+		     || data[cnt].self_pc < sortsym[runp->idx]->addr
+		     || data[cnt].self_pc >= (sortsym[runp->idx]->addr
+					      + sortsym[runp->idx]->size)))
+	    runp = runp->next;
+
+	  if (runp == NULL)
+	    {
+	      /* We need a new entry.  */
+	      struct arc_list *newp = (struct arc_list *)
+		obstack_alloc (&ob_list, sizeof (struct arc_list));
+
+	      newp->idx = find_symbol (data[cnt].self_pc);
+	      newp->count = data[cnt].count;
+	      newp->next = sym->tos;
+	      sym->tos = newp;
+	    }
+	  else
+	    /* Increment the counter for the found entry.  */
+	    runp->count += data[cnt].count;
+	}
+    }
+}
+
+
+static int
+countorder (const void *p1, const void *p2)
+{
+  struct known_symbol *s1 = (struct known_symbol *) p1;
+  struct known_symbol *s2 = (struct known_symbol *) p2;
+
+  if (s1->ticks != s2->ticks)
+    return (int) (s2->ticks - s1->ticks);
+
+  if (s1->calls != s2->calls)
+    return (int) (s2->calls - s1->calls);
+
+  return strcmp (s1->name, s2->name);
+}
+
+
+static double tick_unit;
+static uintmax_t cumu_ticks;
+
+static void
+printflat (const void *node, VISIT value, int level)
+{
+  if (value == leaf || value == postorder)
+    {
+      struct known_symbol *s = *(struct known_symbol **) node;
+
+      cumu_ticks += s->ticks;
+
+      printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f           %s\n",
+	      total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
+	      tick_unit * cumu_ticks,
+	      tick_unit * s->ticks,
+	      s->calls,
+	      s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
+	      /* FIXME: don't know about called functions.  */
+	      s->name);
+    }
+}
+
+
+/* ARGUSED */
+static void
+freenoop (void *p)
+{
+}
+
+
+static void
+generate_flat_profile (struct profdata *profdata)
+{
+  size_t n;
+  void *data = NULL;
+
+  tick_unit = 1.0 / profdata->hist_hdr->prof_rate;
+
+  printf ("Flat profile:\n\n"
+	  "Each sample counts as %g %s.\n",
+	  tick_unit, profdata->hist_hdr->dimen);
+  fputs ("  %   cumulative   self              self     total\n"
+	 " time   seconds   seconds    calls  us/call  us/call  name\n",
+	 stdout);
+
+  for (n = 0; n < symidx; ++n)
+    if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
+      tsearch (sortsym[n], &data, countorder);
+
+  twalk (data, printflat);
+
+  tdestroy (data, freenoop);
+}
+
+
+static void
+generate_call_graph (struct profdata *profdata)
+{
+  size_t cnt;
+
+  puts ("\nindex % time    self  children    called     name\n");
+
+  for (cnt = 0; cnt < symidx; ++cnt)
+    if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
+      {
+	struct arc_list *runp;
+	size_t n;
+
+	/* First print the from-information.  */
+	runp = sortsym[cnt]->froms;
+	while (runp != NULL)
+	  {
+	    printf ("            %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX "   %s",
+		    (runp->idx != (size_t) -1l
+		     ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
+		    0.0, /* FIXME: what's time for the children, recursive */
+		    runp->count, sortsym[cnt]->calls,
+		    (runp->idx != (size_t) -1l ?
+		     sortsym[runp->idx]->name : "<UNKNOWN>"));
+
+	    if (runp->idx != (size_t) -1l)
+	      printf (" [%Zd]", runp->idx);
+	    putchar_unlocked ('\n');
+
+	    runp = runp->next;
+	  }
+
+	/* Info about the function itself.  */
+	n = printf ("[%Zu]", cnt);
+	printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX "         %s [%Zd]\n",
+		(int) (7 - n), " ",
+		total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
+		sortsym[cnt]->ticks * tick_unit,
+		0.0, /* FIXME: what's time for the children, recursive */
+		sortsym[cnt]->calls,
+		sortsym[cnt]->name, cnt);
+
+	/* Info about the functions this function calls.  */
+	runp = sortsym[cnt]->tos;
+	while (runp != NULL)
+	  {
+	    printf ("            %8.2f%8.2f%9" PRIdMAX "/",
+		    (runp->idx != (size_t) -1l
+		     ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
+		    0.0, /* FIXME: what's time for the children, recursive */
+		    runp->count);
+
+	    if (runp->idx != (size_t) -1l)
+	      printf ("%-9" PRIdMAX "   %s [%Zd]\n",
+		      sortsym[runp->idx]->calls,
+		      sortsym[runp->idx]->name,
+		      runp->idx);
+	    else
+	      fputs ("???         <UNKNOWN>\n\n", stdout);
+
+	    runp = runp->next;
+	  }
+
+	fputs ("-----------------------------------------------\n", stdout);
+      }
+}
+
+
+static void
+generate_call_pair_list (struct profdata *profdata)
+{
+  size_t cnt;
+
+  for (cnt = 0; cnt < symidx; ++cnt)
+    if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
+      {
+	struct arc_list *runp;
+
+	/* First print the incoming arcs.  */
+	runp = sortsym[cnt]->froms;
+	while (runp != NULL)
+	  {
+	    if (runp->idx == (size_t) -1l)
+	      printf ("\
+<UNKNOWN>                          %-34s %9" PRIdMAX "\n",
+		      sortsym[cnt]->name, runp->count);
+	    runp = runp->next;
+	  }
+
+	/* Next the outgoing arcs.  */
+	runp = sortsym[cnt]->tos;
+	while (runp != NULL)
+	  {
+	    printf ("%-34s %-34s %9" PRIdMAX "\n",
+		    sortsym[cnt]->name,
+		    (runp->idx != (size_t) -1l
+		     ? sortsym[runp->idx]->name : "<UNKNOWN>"),
+		    runp->count);
+	    runp = runp->next;
+	  }
+      }
+}
diff --git a/REORG.TODO/elf/static-stubs.c b/REORG.TODO/elf/static-stubs.c
new file mode 100644
index 0000000000..f81d5b792b
--- /dev/null
+++ b/REORG.TODO/elf/static-stubs.c
@@ -0,0 +1,46 @@
+/* Stub implementations of functions to link into statically linked
+   programs without needing libgcc_eh.
+   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Avoid backtrace (and so _Unwind_Backtrace) dependencies from
+   sysdeps/unix/sysv/linux/libc_fatal.c.  */
+#include <sysdeps/posix/libc_fatal.c>
+
+#include <stdlib.h>
+#include <unwind.h>
+
+/* These programs do not use thread cancellation, so _Unwind_Resume
+   and the personality routine are never actually called.  */
+
+void
+_Unwind_Resume (struct _Unwind_Exception *exc __attribute__ ((unused)))
+{
+  abort ();
+}
+
+_Unwind_Reason_Code
+__gcc_personality_v0 (int version __attribute__ ((unused)),
+		      _Unwind_Action actions __attribute__ ((unused)),
+		      _Unwind_Exception_Class exception_class
+		      __attribute__ ((unused)),
+		      struct _Unwind_Exception *ue_header
+		      __attribute__ ((unused)),
+		      struct _Unwind_Context *context __attribute__ ((unused)))
+{
+  abort ();
+}
diff --git a/REORG.TODO/elf/testobj.h b/REORG.TODO/elf/testobj.h
new file mode 100644
index 0000000000..1707ae340e
--- /dev/null
+++ b/REORG.TODO/elf/testobj.h
@@ -0,0 +1,28 @@
+extern int preload (int a);
+
+extern int foo (int);
+
+extern int obj1func1 (int);
+
+extern int obj1func2 (int);
+
+extern int obj2func1 (int);
+
+extern int obj2func2 (int);
+
+extern int obj3func1 (int);
+
+extern int obj3func2 (int);
+
+extern int obj4func1 (int);
+
+extern int obj4func2 (int);
+
+extern int obj5func1 (int);
+
+extern int obj5func2 (int);
+
+extern int obj6func1 (int);
+
+extern int obj6func2 (int);
+
diff --git a/REORG.TODO/elf/testobj1.c b/REORG.TODO/elf/testobj1.c
new file mode 100644
index 0000000000..5ab20efd62
--- /dev/null
+++ b/REORG.TODO/elf/testobj1.c
@@ -0,0 +1,25 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "testobj.h"
+
+int
+obj1func1 (int a __attribute__ ((unused)))
+{
+  return 42;
+}
+
+int
+obj1func2 (int a)
+{
+  return foo (a) + 10;
+}
+
+int
+preload (int a)
+{
+  int (*fp) (int) = dlsym (RTLD_NEXT, "preload");
+  if (fp != NULL)
+    return fp (a) + 10;
+  return 10;
+}
diff --git a/REORG.TODO/elf/testobj1_1.c b/REORG.TODO/elf/testobj1_1.c
new file mode 100644
index 0000000000..2541a5ad1b
--- /dev/null
+++ b/REORG.TODO/elf/testobj1_1.c
@@ -0,0 +1,7 @@
+#include "testobj.h"
+
+int
+obj1func1 (int a)
+{
+  return 42 + obj1func2 (a);
+}
diff --git a/REORG.TODO/elf/testobj2.c b/REORG.TODO/elf/testobj2.c
new file mode 100644
index 0000000000..7e4b610982
--- /dev/null
+++ b/REORG.TODO/elf/testobj2.c
@@ -0,0 +1,32 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testobj.h"
+
+int
+obj2func1 (int a __attribute__ ((unused)))
+{
+  return 43;
+}
+
+int
+obj2func2 (int a)
+{
+  return obj1func1 (a) + 10;
+}
+
+int
+preload (int a)
+{
+  int (*fp) (int) = dlsym (RTLD_NEXT, "preload");
+  if (fp != NULL)
+    return fp (a) + 10;
+  return 10;
+}
+
+void
+p (void)
+{
+  puts ("hello world");
+}
diff --git a/REORG.TODO/elf/testobj3.c b/REORG.TODO/elf/testobj3.c
new file mode 100644
index 0000000000..c025ff631a
--- /dev/null
+++ b/REORG.TODO/elf/testobj3.c
@@ -0,0 +1,26 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "testobj.h"
+
+
+int
+obj3func1 (int a __attribute__ ((unused)))
+{
+  return 44;
+}
+
+int
+obj3func2 (int a)
+{
+  return foo (a) + 42;
+}
+
+int
+preload (int a)
+{
+  int (*fp) (int) = dlsym (RTLD_NEXT, "preload");
+  if (fp != NULL)
+    return fp (a) + 10;
+  return 10;
+}
diff --git a/REORG.TODO/elf/testobj4.c b/REORG.TODO/elf/testobj4.c
new file mode 100644
index 0000000000..2729ba32be
--- /dev/null
+++ b/REORG.TODO/elf/testobj4.c
@@ -0,0 +1,25 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "testobj.h"
+
+int
+obj4func1 (int a __attribute__ ((unused)))
+{
+  return 55;
+}
+
+int
+obj4func2 (int a)
+{
+  return foo (a) + 43;
+}
+
+int
+preload (int a)
+{
+  int (*fp) (int) = dlsym (RTLD_NEXT, "preload");
+  if (fp != NULL)
+    return fp (a) + 10;
+  return 10;
+}
diff --git a/REORG.TODO/elf/testobj5.c b/REORG.TODO/elf/testobj5.c
new file mode 100644
index 0000000000..9675cad88d
--- /dev/null
+++ b/REORG.TODO/elf/testobj5.c
@@ -0,0 +1,26 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "testobj.h"
+
+
+int
+obj5func1 (int a __attribute__ ((unused)))
+{
+  return 66;
+}
+
+int
+obj5func2 (int a)
+{
+  return foo (a) + 44;
+}
+
+int
+preload (int a)
+{
+  int (*fp) (int) = dlsym (RTLD_NEXT, "preload");
+  if (fp != NULL)
+    return fp (a) + 10;
+  return 10;
+}
diff --git a/REORG.TODO/elf/testobj6.c b/REORG.TODO/elf/testobj6.c
new file mode 100644
index 0000000000..fcba01631d
--- /dev/null
+++ b/REORG.TODO/elf/testobj6.c
@@ -0,0 +1,19 @@
+#include "testobj.h"
+
+int
+obj6func1 (int a __attribute__ ((unused)))
+{
+  return 77;
+}
+
+int
+obj6func2 (int a)
+{
+  return foo (a) + 46;
+}
+
+int
+preload (int a)
+{
+  return a;
+}
diff --git a/REORG.TODO/elf/tls-macros.h b/REORG.TODO/elf/tls-macros.h
new file mode 100644
index 0000000000..e25e33b0f0
--- /dev/null
+++ b/REORG.TODO/elf/tls-macros.h
@@ -0,0 +1,25 @@
+/* Macros to support TLS testing in times of missing compiler support.  */
+
+#define COMMON_INT_DEF(x) \
+  asm (".tls_common " #x ",4,4")
+/* XXX Until we get compiler support we don't need declarations.  */
+#define COMMON_INT_DECL(x)
+
+/* XXX This definition will probably be machine specific, too.  */
+#define VAR_INT_DEF(x) \
+  asm (".section .tdata\n\t"						      \
+       ".globl " #x "\n"						      \
+       ".balign 4\n"							      \
+       #x ":\t.long 0\n\t"						      \
+       ".size " #x ",4\n\t"						      \
+       ".previous")
+/* XXX Until we get compiler support we don't need declarations.  */
+#define VAR_INT_DECL(x)
+
+#include_next <tls-macros.h>
+
+  /* XXX Each architecture must have its own asm for now.  */
+#if !defined TLS_LE || !defined TLS_IE \
+      || !defined TLS_LD || !defined TLS_GD
+# error "No support for this architecture so far."
+#endif
diff --git a/REORG.TODO/elf/tlsdeschtab.h b/REORG.TODO/elf/tlsdeschtab.h
new file mode 100644
index 0000000000..3091d8b420
--- /dev/null
+++ b/REORG.TODO/elf/tlsdeschtab.h
@@ -0,0 +1,164 @@
+/* Hash table for TLS descriptors.
+   Copyright (C) 2005-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Alexandre Oliva  <aoliva@redhat.com>
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef TLSDESCHTAB_H
+# define TLSDESCHTAB_H 1
+
+#include <atomic.h>
+
+# ifdef SHARED
+
+#  include <inline-hashtab.h>
+
+inline static int
+hash_tlsdesc (void *p)
+{
+  struct tlsdesc_dynamic_arg *td = p;
+
+  /* We know all entries are for the same module, so ti_offset is the
+     only distinguishing entry.  */
+  return td->tlsinfo.ti_offset;
+}
+
+inline static int
+eq_tlsdesc (void *p, void *q)
+{
+  struct tlsdesc_dynamic_arg *tdp = p, *tdq = q;
+
+  return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
+}
+
+inline static size_t
+map_generation (struct link_map *map)
+{
+  size_t idx = map->l_tls_modid;
+  struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+  /* Find the place in the dtv slotinfo list.  */
+  do
+    {
+      /* Does it fit in the array of this list element?  */
+      if (idx < listp->len)
+	{
+	  /* We should never get here for a module in static TLS, so
+	     we can assume that, if the generation count is zero, we
+	     still haven't determined the generation count for this
+	     module.  */
+	  if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
+	    return listp->slotinfo[idx].gen;
+	  else
+	    break;
+	}
+      idx -= listp->len;
+      listp = listp->next;
+    }
+  while (listp != NULL);
+
+  /* If we get to this point, the module still hasn't been assigned an
+     entry in the dtv slotinfo data structures, and it will when we're
+     done with relocations.  At that point, the module will get a
+     generation number that is one past the current generation, so
+     return exactly that.  */
+  return GL(dl_tls_generation) + 1;
+}
+
+void *
+internal_function
+_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
+{
+  struct hashtab *ht;
+  void **entry;
+  struct tlsdesc_dynamic_arg *td, test;
+
+  /* FIXME: We could use a per-map lock here, but is it worth it?  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  ht = map->l_mach.tlsdesc_table;
+  if (! ht)
+    {
+      ht = htab_create ();
+      if (! ht)
+	{
+	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+	  return 0;
+	}
+      map->l_mach.tlsdesc_table = ht;
+    }
+
+  test.tlsinfo.ti_module = map->l_tls_modid;
+  test.tlsinfo.ti_offset = ti_offset;
+  entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc);
+  if (! entry)
+    {
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+      return 0;
+    }
+
+  if (*entry)
+    {
+      td = *entry;
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+      return td;
+    }
+
+  *entry = td = malloc (sizeof (struct tlsdesc_dynamic_arg));
+  /* This may be higher than the map's generation, but it doesn't
+     matter much.  Worst case, we'll have one extra DTV update per
+     thread.  */
+  td->gen_count = map_generation (map);
+  td->tlsinfo = test.tlsinfo;
+
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+  return td;
+}
+
+# endif /* SHARED */
+
+/* The idea of the following two functions is to stop multiple threads
+   from attempting to resolve the same TLS descriptor without busy
+   waiting.  Ideally, we should be able to release the lock right
+   after changing td->entry, and then using say a condition variable
+   or a futex wake to wake up any waiting threads, but let's try to
+   avoid introducing such dependencies.  */
+
+static int
+_dl_tlsdesc_resolve_early_return_p (struct tlsdesc volatile *td, void *caller)
+{
+  if (caller != atomic_load_relaxed (&td->entry))
+    return 1;
+
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  if (caller != atomic_load_relaxed (&td->entry))
+    {
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+      return 1;
+    }
+
+  atomic_store_relaxed (&td->entry, _dl_tlsdesc_resolve_hold);
+
+  return 0;
+}
+
+static void
+_dl_tlsdesc_wake_up_held_fixups (void)
+{
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+}
+
+#endif
diff --git a/REORG.TODO/elf/tst-_dl_addr_inside_object.c b/REORG.TODO/elf/tst-_dl_addr_inside_object.c
new file mode 100644
index 0000000000..1604b8df63
--- /dev/null
+++ b/REORG.TODO/elf/tst-_dl_addr_inside_object.c
@@ -0,0 +1,222 @@
+/* Unit test for _dl_addr_inside_object.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <link.h>
+#include <elf.h>
+#include <libc-symbols.h>
+
+extern int internal_function _dl_addr_inside_object (struct link_map *l,
+						     const ElfW(Addr) addr);
+
+static int
+do_test (void)
+{
+  int ret, err = 0;
+  ElfW(Addr) addr;
+  struct link_map map;
+  ElfW(Phdr) header;
+  map.l_phdr = &header;
+  map.l_phnum = 1;
+  map.l_addr = 0x0;
+  /* Segment spans 0x2000 -> 0x4000.  */
+  header.p_vaddr = 0x2000;
+  header.p_memsz = 0x2000;
+  header.p_type = PT_LOAD;
+  /* Address is above the segment e.g. > 0x4000.  */
+  addr = 0x5000;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: Above: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+        printf ("FAIL: Above: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: Above: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is inside the segment e.g. 0x2000 < addr < 0x4000.  */
+  addr = 0x3000;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("FAIL: Inside: Address is detected as outside the segment.\n");
+	err++;
+	break;
+      case 1:
+        printf ("PASS: Inside: Address is detected as inside the segment.\n");
+	break;
+      default:
+	printf ("FAIL: Inside: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is below the segment e.g. < 0x2000.  */
+  addr = 0x1000;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: Below: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+        printf ("FAIL: Below: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: Below: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is in the segment and addr == p_vaddr.  */
+  addr = 0x2000;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("FAIL: At p_vaddr: Address is detected as outside the segment.\n");
+	err++;
+	break;
+      case 1:
+        printf ("PASS: At p_vaddr: Address is detected as inside the segment.\n");
+	break;
+      default:
+	printf ("FAIL: At p_vaddr: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is in the segment and addr == p_vaddr + p_memsz - 1.  */
+  addr = 0x2000 + 0x2000 - 0x1;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("FAIL: At p_memsz-1: Address is detected as outside the segment.\n");
+	err++;
+	break;
+      case 1:
+        printf ("PASS: At p_memsz-1: Address is detected as inside the segment.\n");
+	break;
+      default:
+	printf ("FAIL: At p_memsz-1: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is outside the segment and addr == p_vaddr + p_memsz.  */
+  addr = 0x2000 + 0x2000;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: At p_memsz: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+        printf ("FAIL: At p_memsz: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: At p_memsz: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is outside the segment and p_vaddr at maximum address.  */
+  addr = 0x0 - 0x2;
+  header.p_vaddr = 0x0 - 0x1;
+  header.p_memsz = 0x1;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: At max: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+        printf ("FAIL: At max: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: At max: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is outside the segment and p_vaddr at minimum address.  */
+  addr = 0x1;
+  header.p_vaddr = 0x0;
+  header.p_memsz = 0x1;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: At min: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+        printf ("FAIL: At min: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: At min: Invalid return value.\n");
+	exit (1);
+    }
+  /* Address is always inside the segment with p_memsz at max.  */
+  addr = 0x0;
+  header.p_vaddr = 0x0;
+  header.p_memsz = 0x0 - 0x1;
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("FAIL: At maxmem: Address is detected as outside the segment.\n");
+	err++;
+	break;
+      case 1:
+        printf ("PASS: At maxmem: Address is detected as inside the segment.\n");
+	break;
+      default:
+	printf ("FAIL: At maxmem: Invalid return value.\n");
+	exit (1);
+    }
+  /* Attempt to wrap addr into the segment.
+     Pick a load address in the middle of the address space.
+     Place the test address at 0x0 so it wraps to the middle again.  */
+  map.l_addr = 0x0 - 0x1;
+  map.l_addr = map.l_addr / 2;
+  addr = 0;
+  /* Setup a segment covering 1/2 the address space.  */
+  header.p_vaddr = 0x0;
+  header.p_memsz = 0x0 - 0x1 - map.l_addr;
+  /* No matter where you place addr everything is shifted modulo l_addr
+     and even with this underflow you're always 1 byte away from being
+     in the range.  */
+  ret = _dl_addr_inside_object (&map, addr);
+  switch (ret)
+    {
+      case 0:
+	printf ("PASS: Underflow: Address is detected as outside the segment.\n");
+	break;
+      case 1:
+	printf ("FAIL: Underflow: Address is detected as inside the segment.\n");
+	err++;
+	break;
+      default:
+	printf ("FAIL: Underflow: Invalid return value.\n");
+	exit (1);
+    }
+
+  return err;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-addr1.c b/REORG.TODO/elf/tst-addr1.c
new file mode 100644
index 0000000000..68ff74aabd
--- /dev/null
+++ b/REORG.TODO/elf/tst-addr1.c
@@ -0,0 +1,25 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+  Dl_info i;
+  if (dladdr (&printf, &i) == 0)
+    {
+      puts ("not found");
+      return 1;
+    }
+  printf ("found symbol %s in %s\n", i.dli_sname, i.dli_fname);
+  return i.dli_sname == NULL
+	 || (strcmp (i.dli_sname, "printf") != 0
+	     /* On architectures which create PIC code by default
+		&printf may resolve to an address in libc.so
+		rather than in the binary.  printf and _IO_printf
+		are aliased and which one comes first in the
+		hash table is up to the linker.  */
+	     && strcmp (i.dli_sname, "_IO_printf") != 0);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-align.c b/REORG.TODO/elf/tst-align.c
new file mode 100644
index 0000000000..01b0b4ffb3
--- /dev/null
+++ b/REORG.TODO/elf/tst-align.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2003-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-alignmod.so";
+  int result = 0;
+  void (*fp) (int *);
+  void *h;
+
+  h = dlopen (modname, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname, dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
+      exit (1);
+    }
+
+  fp (&result);
+
+  dlclose (h);
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-align2.c b/REORG.TODO/elf/tst-align2.c
new file mode 100644
index 0000000000..78b66be20a
--- /dev/null
+++ b/REORG.TODO/elf/tst-align2.c
@@ -0,0 +1,155 @@
+/* Copyright (C) 2005-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <tst-stack-align.h>
+#include <unistd.h>
+
+static int res, fds[2], result;
+static bool test_destructors;
+
+extern void in_dso (int *, bool *, int *);
+
+static void __attribute__ ((constructor)) con (void)
+{
+  res = TEST_STACK_ALIGN () ? -1 : 1;
+}
+
+static void __attribute__ ((destructor)) des (void)
+{
+  if (!test_destructors)
+    return;
+
+  char c = TEST_STACK_ALIGN () ? 'B' : 'A';
+  write (fds[1], &c, 1);
+}
+
+static int
+do_test (void)
+{
+  if (!res)
+    {
+      puts ("binary's constructor has not been run");
+      result = 1;
+    }
+  else if (res != 1)
+    {
+      puts ("binary's constructor has been run without sufficient alignment");
+      result = 1;
+    }
+
+  if (TEST_STACK_ALIGN ())
+    {
+      puts ("insufficient stack alignment in do_test");
+      result = 1;
+    }
+
+  in_dso (&result, &test_destructors, &fds[1]);
+
+  if (pipe (fds) < 0)
+    {
+      printf ("couldn't create pipe: %m\n");
+      return 1;
+    }
+
+  pid_t pid = fork ();
+  if (pid < 0)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+
+  if (!pid)
+    {
+      close (fds[0]);
+      test_destructors = true;
+      exit (0);
+    }
+
+  close (fds[1]);
+
+  unsigned char c;
+  ssize_t len;
+  int des_seen = 0, dso_des_seen = 0;
+  while ((len = TEMP_FAILURE_RETRY (read (fds[0], &c, 1))) > 0)
+    {
+      switch (c)
+        {
+        case 'B':
+          puts ("insufficient alignment in binary's destructor");
+          result = 1;
+          /* FALLTHROUGH */
+        case 'A':
+          des_seen++;
+          break;
+        case 'D':
+          puts ("insufficient alignment in DSO destructor");
+          result = 1;
+          /* FALLTHROUGH */
+        case 'C':
+          dso_des_seen++;
+          break;
+        default:
+          printf ("unexpected character %x read from pipe", c);
+          result = 1;
+          break;
+        }
+    }
+
+  close (fds[0]);
+
+  if (des_seen != 1)
+    {
+      printf ("binary destructor run %d times instead of once\n", des_seen);
+      result = 1;
+    }
+
+  if (dso_des_seen != 1)
+    {
+      printf ("DSO destructor run %d times instead of once\n", dso_des_seen);
+      result = 1;
+    }
+
+  int status;
+  pid_t termpid;
+  termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+  if (termpid == -1)
+    {
+      printf ("waitpid failed: %m\n");
+      result = 1;
+    }
+  else if (termpid != pid)
+    {
+      printf ("waitpid returned %ld != %ld\n",
+	      (long int) termpid, (long int) pid);
+      result = 1;
+    }
+  else if (!WIFEXITED (status) || WEXITSTATUS (status))
+    {
+      puts ("child hasn't exited with exit status 0");
+      result = 1;
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-alignmod.c b/REORG.TODO/elf/tst-alignmod.c
new file mode 100644
index 0000000000..b5e47be0bd
--- /dev/null
+++ b/REORG.TODO/elf/tst-alignmod.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2003-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static int res, *resp;
+
+static void __attribute__((constructor))
+con (void)
+{
+  res = TEST_STACK_ALIGN () ? -1 : 1;
+}
+
+void
+in_dso (int *result)
+{
+  if (!res)
+    {
+      puts ("constructor has not been run");
+      *result = 1;
+    }
+  else if (res != 1)
+    {
+      puts ("constructor has been run without sufficient alignment");
+      *result = 1;
+    }
+
+  resp = result;
+}
+
+static void __attribute__((destructor))
+des (void)
+{
+  if (TEST_STACK_ALIGN ())
+    *resp = 1;
+}
diff --git a/REORG.TODO/elf/tst-alignmod2.c b/REORG.TODO/elf/tst-alignmod2.c
new file mode 100644
index 0000000000..f338ab5c27
--- /dev/null
+++ b/REORG.TODO/elf/tst-alignmod2.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+#include <unistd.h>
+
+static int res, *fdp;
+static bool *test_destructorsp;
+
+static void __attribute__((constructor))
+con (void)
+{
+  res = TEST_STACK_ALIGN () ? -1 : 1;
+}
+
+void
+in_dso (int *result, bool *test_destructors, int *fd)
+{
+  if (!res)
+    {
+      puts ("constructor has not been run");
+      *result = 1;
+    }
+  else if (res != 1)
+    {
+      puts ("constructor has been run without sufficient alignment");
+      *result = 1;
+    }
+
+  test_destructorsp = test_destructors;
+  fdp = fd;
+}
+
+static void __attribute__((destructor))
+des (void)
+{
+  if (!test_destructorsp || !*test_destructorsp)
+    return;
+
+  char c = TEST_STACK_ALIGN () ? 'D' : 'C';
+  write (*fdp, &c, 1);
+}
diff --git a/REORG.TODO/elf/tst-array1-static.c b/REORG.TODO/elf/tst-array1-static.c
new file mode 100644
index 0000000000..21539a4212
--- /dev/null
+++ b/REORG.TODO/elf/tst-array1-static.c
@@ -0,0 +1 @@
+#include "tst-array1.c"
diff --git a/REORG.TODO/elf/tst-array1.c b/REORG.TODO/elf/tst-array1.c
new file mode 100644
index 0000000000..e998932b36
--- /dev/null
+++ b/REORG.TODO/elf/tst-array1.c
@@ -0,0 +1,103 @@
+#include <unistd.h>
+
+/* Give init non-default priority so that it runs before init_array.  */
+static void init (void) __attribute__ ((constructor (1000)));
+
+static void
+init (void)
+{
+  write (STDOUT_FILENO, "init\n", 5);
+}
+
+/* Give fini the same priority as init.  */
+static void fini (void) __attribute__ ((destructor (1000)));
+
+static void
+fini (void)
+{
+  write (STDOUT_FILENO, "fini\n", 5);
+}
+
+static void
+preinit_0 (void)
+{
+  write (STDOUT_FILENO, "preinit array 0\n", 16);
+}
+
+static void
+preinit_1 (void)
+{
+  write (STDOUT_FILENO, "preinit array 1\n", 16);
+}
+
+static void
+preinit_2 (void)
+{
+  write (STDOUT_FILENO, "preinit array 2\n", 16);
+}
+
+void (*const preinit_array []) (void)
+     __attribute__ ((section (".preinit_array"), aligned (sizeof (void *)))) =
+{
+  &preinit_0,
+  &preinit_1,
+  &preinit_2
+};
+
+static void
+init_0 (void)
+{
+  write (STDOUT_FILENO, "init array 0\n", 13);
+}
+
+static void
+init_1 (void)
+{
+  write (STDOUT_FILENO, "init array 1\n", 13);
+}
+
+static void
+init_2 (void)
+{
+  write (STDOUT_FILENO, "init array 2\n", 13);
+}
+
+void (*init_array []) (void)
+     __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+  &init_1,
+  &init_2
+};
+
+static void
+fini_0 (void)
+{
+  write (STDOUT_FILENO, "fini array 0\n", 13);
+}
+
+static void
+fini_1 (void)
+{
+  write (STDOUT_FILENO, "fini array 1\n", 13);
+}
+
+static void
+fini_2 (void)
+{
+  write (STDOUT_FILENO, "fini array 2\n", 13);
+}
+
+void (*fini_array []) (void)
+     __attribute__ ((section (".fini_array"), aligned (sizeof (void *)))) =
+{
+  &fini_0,
+  &fini_1,
+  &fini_2
+};
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-array1.exp b/REORG.TODO/elf/tst-array1.exp
new file mode 100644
index 0000000000..cfcec9de0f
--- /dev/null
+++ b/REORG.TODO/elf/tst-array1.exp
@@ -0,0 +1,11 @@
+preinit array 0
+preinit array 1
+preinit array 2
+init
+init array 0
+init array 1
+init array 2
+fini array 2
+fini array 1
+fini array 0
+fini
diff --git a/REORG.TODO/elf/tst-array2.c b/REORG.TODO/elf/tst-array2.c
new file mode 100644
index 0000000000..21539a4212
--- /dev/null
+++ b/REORG.TODO/elf/tst-array2.c
@@ -0,0 +1 @@
+#include "tst-array1.c"
diff --git a/REORG.TODO/elf/tst-array2.exp b/REORG.TODO/elf/tst-array2.exp
new file mode 100644
index 0000000000..ed203525b5
--- /dev/null
+++ b/REORG.TODO/elf/tst-array2.exp
@@ -0,0 +1,19 @@
+preinit array 0
+preinit array 1
+preinit array 2
+DSO init
+DSO init array 0
+DSO init array 1
+DSO init array 2
+init
+init array 0
+init array 1
+init array 2
+fini array 2
+fini array 1
+fini array 0
+fini
+DSO fini array 2
+DSO fini array 1
+DSO fini array 0
+DSO fini
diff --git a/REORG.TODO/elf/tst-array2dep.c b/REORG.TODO/elf/tst-array2dep.c
new file mode 100644
index 0000000000..2f920cdc8d
--- /dev/null
+++ b/REORG.TODO/elf/tst-array2dep.c
@@ -0,0 +1,71 @@
+#include <unistd.h>
+
+/* Give init non-default priority so that it runs before init_array.  */
+static void init (void) __attribute__ ((constructor (1000)));
+
+static void
+init (void)
+{
+  write (STDOUT_FILENO, "DSO init\n", 9);
+}
+
+/* Give fini the same priority as init.  */
+static void fini (void) __attribute__ ((destructor (1000)));
+
+static void
+fini (void)
+{
+  write (STDOUT_FILENO, "DSO fini\n", 9);
+}
+
+static void
+init_0 (void)
+{
+  write (STDOUT_FILENO, "DSO init array 0\n", 17);
+}
+
+static void
+init_1 (void)
+{
+  write (STDOUT_FILENO, "DSO init array 1\n", 17);
+}
+
+static void
+init_2 (void)
+{
+  write (STDOUT_FILENO, "DSO init array 2\n", 17);
+}
+
+void (*init_array []) (void)
+     __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+  &init_1,
+  &init_2
+};
+
+static void
+fini_0 (void)
+{
+  write (STDOUT_FILENO, "DSO fini array 0\n", 17);
+}
+
+static void
+fini_1 (void)
+{
+  write (STDOUT_FILENO, "DSO fini array 1\n", 17);
+}
+
+static void
+fini_2 (void)
+{
+  write (STDOUT_FILENO, "DSO fini array 2\n", 17);
+}
+
+void (*fini_array []) (void)
+     __attribute__ ((section (".fini_array"), aligned (sizeof (void *)))) =
+{
+  &fini_0,
+  &fini_1,
+  &fini_2
+};
diff --git a/REORG.TODO/elf/tst-array3.c b/REORG.TODO/elf/tst-array3.c
new file mode 100644
index 0000000000..21539a4212
--- /dev/null
+++ b/REORG.TODO/elf/tst-array3.c
@@ -0,0 +1 @@
+#include "tst-array1.c"
diff --git a/REORG.TODO/elf/tst-array4.c b/REORG.TODO/elf/tst-array4.c
new file mode 100644
index 0000000000..ac3d4eb716
--- /dev/null
+++ b/REORG.TODO/elf/tst-array4.c
@@ -0,0 +1,18 @@
+#include <dlfcn.h>
+
+#define main array1_main
+#include "tst-array1.c"
+#undef main
+
+int
+main (void)
+{
+  void *handle = dlopen ("tst-array2dep.so", RTLD_LAZY);
+
+  array1_main ();
+
+  if (handle != NULL)
+    dlclose (handle);
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-array4.exp b/REORG.TODO/elf/tst-array4.exp
new file mode 100644
index 0000000000..560444d2e8
--- /dev/null
+++ b/REORG.TODO/elf/tst-array4.exp
@@ -0,0 +1,19 @@
+preinit array 0
+preinit array 1
+preinit array 2
+init
+init array 0
+init array 1
+init array 2
+DSO init
+DSO init array 0
+DSO init array 1
+DSO init array 2
+DSO fini array 2
+DSO fini array 1
+DSO fini array 0
+DSO fini
+fini array 2
+fini array 1
+fini array 0
+fini
diff --git a/REORG.TODO/elf/tst-array5-static.c b/REORG.TODO/elf/tst-array5-static.c
new file mode 100644
index 0000000000..4ef2aba3f3
--- /dev/null
+++ b/REORG.TODO/elf/tst-array5-static.c
@@ -0,0 +1 @@
+#include "tst-array5.c"
diff --git a/REORG.TODO/elf/tst-array5-static.exp b/REORG.TODO/elf/tst-array5-static.exp
new file mode 100644
index 0000000000..b1dc9e467b
--- /dev/null
+++ b/REORG.TODO/elf/tst-array5-static.exp
@@ -0,0 +1,2 @@
+preinit array in executable: tst-array5-static
+init array in executable: tst-array5-static
diff --git a/REORG.TODO/elf/tst-array5.c b/REORG.TODO/elf/tst-array5.c
new file mode 100644
index 0000000000..03a5668326
--- /dev/null
+++ b/REORG.TODO/elf/tst-array5.c
@@ -0,0 +1,50 @@
+#include <string.h>
+#include <unistd.h>
+
+static void
+preinit_0 (int argc __attribute__ ((unused)), char **argv)
+{
+  char *p = strrchr (argv [0], '/');
+
+  if (p == NULL)
+      return;
+
+  p++;
+  size_t len = strlen (p);
+  write (STDOUT_FILENO, "preinit array in executable: ", 29);
+  write (STDOUT_FILENO, p, len);
+  write (STDOUT_FILENO, "\n", 1);
+}
+
+void (*const preinit_array []) (int, char **)
+     __attribute__ ((section (".preinit_array"), aligned (sizeof (void *)))) =
+{
+  &preinit_0,
+};
+
+static void
+init_0 (int argc __attribute__ ((unused)), char **argv)
+{
+  char *p = strrchr (argv [0], '/');
+
+  if (p == NULL)
+      return;
+
+  p++;
+  size_t len = strlen (p);
+  write (STDOUT_FILENO, "init array in executable: ", 26);
+  write (STDOUT_FILENO, p, len);
+  write (STDOUT_FILENO, "\n", 1);
+}
+
+void (*const init_array []) (int, char **)
+     __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+};
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-array5.exp b/REORG.TODO/elf/tst-array5.exp
new file mode 100644
index 0000000000..28b4909833
--- /dev/null
+++ b/REORG.TODO/elf/tst-array5.exp
@@ -0,0 +1,3 @@
+preinit array in executable: tst-array5
+init array in DSO: tst-array5
+init array in executable: tst-array5
diff --git a/REORG.TODO/elf/tst-array5dep.c b/REORG.TODO/elf/tst-array5dep.c
new file mode 100644
index 0000000000..570d282af4
--- /dev/null
+++ b/REORG.TODO/elf/tst-array5dep.c
@@ -0,0 +1,23 @@
+#include <string.h>
+#include <unistd.h>
+
+static void
+init_0 (int argc __attribute__ ((unused)), char **argv)
+{
+  char *p = strrchr (argv [0], '/');
+
+  if (p == NULL)
+      return;
+
+  p++;
+  size_t len = strlen (p);
+  write (STDOUT_FILENO, "init array in DSO: ", 19);
+  write (STDOUT_FILENO, p, len);
+  write (STDOUT_FILENO, "\n", 1);
+}
+
+void (*const init_array []) (int, char **)
+     __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+};
diff --git a/REORG.TODO/elf/tst-audit1.c b/REORG.TODO/elf/tst-audit1.c
new file mode 100644
index 0000000000..63656b4ee9
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit1.c
@@ -0,0 +1 @@
+#include "../io/pwd.c"
diff --git a/REORG.TODO/elf/tst-audit11.c b/REORG.TODO/elf/tst-audit11.c
new file mode 100644
index 0000000000..ff91a6bd6d
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit11.c
@@ -0,0 +1,35 @@
+/* Test version symbol binding can find a DSO replaced by la_objsearch.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+do_test (void)
+{
+  puts ("Start");
+  if (dlopen ("$ORIGIN/tst-audit11mod1.so", RTLD_LAZY) == NULL)
+    {
+      printf ("module not loaded: %s\n", dlerror ());
+      return 1;
+    }
+  puts ("OK");
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-audit11mod1.c b/REORG.TODO/elf/tst-audit11mod1.c
new file mode 100644
index 0000000000..0c0f5c6838
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit11mod1.c
@@ -0,0 +1,24 @@
+/* DSO directly opened by tst-audit11.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+extern int f2 (void);
+int
+f1 (void)
+{
+  return f2 ();
+}
diff --git a/REORG.TODO/elf/tst-audit11mod2.c b/REORG.TODO/elf/tst-audit11mod2.c
new file mode 100644
index 0000000000..d5eb029744
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit11mod2.c
@@ -0,0 +1,23 @@
+/* DSO indirectly opened by tst-audit11, with symbol versioning.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int
+f2 (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/tst-audit11mod2.map b/REORG.TODO/elf/tst-audit11mod2.map
new file mode 100644
index 0000000000..278787872c
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit11mod2.map
@@ -0,0 +1,22 @@
+/* Symbol versioning for the DSO indirectly opened by tst-audit11.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+V1 {
+  global: f2;
+  local: *;
+};
diff --git a/REORG.TODO/elf/tst-audit12.c b/REORG.TODO/elf/tst-audit12.c
new file mode 100644
index 0000000000..62ac5f28a4
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit12.c
@@ -0,0 +1,48 @@
+/* Test that symbol is bound to a DSO replaced by la_objsearch.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+do_test (void)
+{
+  puts ("Start");
+  void *h = dlopen ("$ORIGIN/tst-audit12mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("module not loaded: %s\n", dlerror ());
+      return 1;
+    }
+  int (*fp) (void) = (int (*) (void)) dlsym (h, "f1");
+  if (fp == NULL)
+    {
+      printf ("function f1 not found: %s\n", dlerror ());
+      return 1;
+    }
+  int res = fp ();
+  if (res != 43)
+    {
+      puts ("incorrect function f2 called");
+      return 1;
+    }
+  printf ("%d is OK\n", res);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-audit12mod1.c b/REORG.TODO/elf/tst-audit12mod1.c
new file mode 100644
index 0000000000..a48795b661
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit12mod1.c
@@ -0,0 +1,24 @@
+/* DSO directly opened by tst-audit12.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+extern int f2 (void);
+int
+f1 (void)
+{
+  return f2 ();
+}
diff --git a/REORG.TODO/elf/tst-audit12mod2.c b/REORG.TODO/elf/tst-audit12mod2.c
new file mode 100644
index 0000000000..593d02dfb6
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit12mod2.c
@@ -0,0 +1,23 @@
+/* Replaced DSO referenced by tst-audit12mod1.so, for tst-audit12.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int
+f2 (void)
+{
+  return 42;
+}
diff --git a/REORG.TODO/elf/tst-audit12mod2.map b/REORG.TODO/elf/tst-audit12mod2.map
new file mode 100644
index 0000000000..11e22bbdee
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit12mod2.map
@@ -0,0 +1,22 @@
+/* Symbol versioning for tst-audit12mod2.so used by tst-audit12.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+V1 {
+  global: f2;
+  local: *;
+};
diff --git a/REORG.TODO/elf/tst-audit12mod3.c b/REORG.TODO/elf/tst-audit12mod3.c
new file mode 100644
index 0000000000..1e01bb8eea
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit12mod3.c
@@ -0,0 +1,23 @@
+/* Replacement DSO loaded by the audit module, for tst-audit12.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int
+f2 (void)
+{
+  return 43;
+}
diff --git a/REORG.TODO/elf/tst-audit2.c b/REORG.TODO/elf/tst-audit2.c
new file mode 100644
index 0000000000..0e66f5c328
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit2.c
@@ -0,0 +1,60 @@
+/* Test case for early TLS initialization in dynamic linker.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#define MAGIC1 0xabcdef72
+#define MAGIC2 0xd8675309
+static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
+static __thread int calloc_called;
+
+#undef calloc
+
+/* This calloc definition will be called by the dynamic linker itself.
+   We test that interposed calloc is called by the dynamic loader, and
+   that TLS is fully initialized by then.  */
+
+void *
+calloc (size_t n, size_t m)
+{
+  if (!calloc_called)
+    {
+      /* Allow our calloc to be called more than once.  */
+      calloc_called = 1;
+      if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+	{
+	  printf ("{%x, %x} != {%x, %x}\n",
+		  magic[0], magic[1], MAGIC1, MAGIC2);
+	  abort ();
+	}
+      magic[0] = MAGIC2;
+      magic[1] = MAGIC1;
+    }
+
+  n *= m;
+  void *ptr = malloc (n);
+  if (ptr != NULL)
+    memset (ptr, '\0', n);
+  return ptr;
+}
+
+static int
+do_test (void)
+{
+  /* Make sure that our calloc is called from the dynamic linker at least
+     once.  */
+  void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+  if (h != NULL)
+    dlclose (h);
+  if (magic[1] != MAGIC1 || magic[0] != MAGIC2)
+    {
+      printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC2, MAGIC1);
+      return 1;
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-audit8.c b/REORG.TODO/elf/tst-audit8.c
new file mode 100644
index 0000000000..63656b4ee9
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit8.c
@@ -0,0 +1 @@
+#include "../io/pwd.c"
diff --git a/REORG.TODO/elf/tst-audit9.c b/REORG.TODO/elf/tst-audit9.c
new file mode 100644
index 0000000000..b9de1bf5a2
--- /dev/null
+++ b/REORG.TODO/elf/tst-audit9.c
@@ -0,0 +1,11 @@
+#include <dlfcn.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+  int (*fp)(void) = dlsym(h, "f");
+  return fp() - 1;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-auditmod1.c b/REORG.TODO/elf/tst-auditmod1.c
new file mode 100644
index 0000000000..573e37abd6
--- /dev/null
+++ b/REORG.TODO/elf/tst-auditmod1.c
@@ -0,0 +1,135 @@
+#include <dlfcn.h>
+#include <link.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <bits/wordsize.h>
+#include <gnu/lib-names.h>
+
+
+unsigned int
+la_version (unsigned int v)
+{
+  setlinebuf (stdout);
+
+  printf ("version: %u\n", v);
+
+  char buf[20];
+  sprintf (buf, "%u", v);
+
+  return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+  if (flag == LA_ACT_CONSISTENT)
+    printf ("activity: consistent\n");
+  else if (flag == LA_ACT_ADD)
+    printf ("activity: add\n");
+  else if (flag == LA_ACT_DELETE)
+    printf ("activity: delete\n");
+  else
+    printf ("activity: unknown activity %u\n", flag);
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+  char buf[100];
+  const char *flagstr;
+  if (flag == LA_SER_ORIG)
+    flagstr = "LA_SET_ORIG";
+  else if (flag == LA_SER_LIBPATH)
+    flagstr = "LA_SER_LIBPATH";
+  else if (flag == LA_SER_RUNPATH)
+    flagstr = "LA_SER_RUNPATH";
+  else if (flag == LA_SER_CONFIG)
+    flagstr = "LA_SER_CONFIG";
+  else if (flag == LA_SER_DEFAULT)
+    flagstr = "LA_SER_DEFAULT";
+  else if (flag == LA_SER_SECURE)
+    flagstr = "LA_SER_SECURE";
+  else
+    {
+       sprintf (buf, "unknown flag %d", flag);
+       flagstr = buf;
+    }
+  printf ("objsearch: %s, %s\n", name, flagstr);
+
+  return (char *) name;
+}
+
+unsigned int
+la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
+{
+  printf ("objopen: %ld, %s\n", lmid, l->l_name);
+
+  return 3;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+  printf ("preinit\n");
+}
+
+unsigned int
+la_objclose  (uintptr_t *cookie)
+{
+  printf ("objclose\n");
+  return 0;
+}
+
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+	      uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+  printf ("symbind32: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+	  symname, (long int) sym->st_value, ndx, *flags);
+
+  return sym->st_value;
+}
+
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+	      uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+  printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+	  symname, (long int) sym->st_value, ndx, *flags);
+
+  return sym->st_value;
+}
+
+#include <tst-audit.h>
+#if (!defined (pltenter) || !defined (pltexit) || !defined (La_regs) \
+     || !defined (La_retval) || !defined (int_retval))
+# error "architecture specific code needed in sysdeps/CPU/tst-audit.h"
+#endif
+
+
+ElfW(Addr)
+pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+	  uintptr_t *defcook, La_regs *regs, unsigned int *flags,
+	  const char *symname, long int *framesizep)
+{
+  printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+	  symname, (long int) sym->st_value, ndx, *flags);
+
+  return sym->st_value;
+}
+
+unsigned int
+pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+	 uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
+	 const char *symname)
+{
+  printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n",
+	  symname, (long int) sym->st_value, ndx,
+	  (ptrdiff_t) outregs->int_retval);
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-auditmod11.c b/REORG.TODO/elf/tst-auditmod11.c
new file mode 100644
index 0000000000..18feb5efc4
--- /dev/null
+++ b/REORG.TODO/elf/tst-auditmod11.c
@@ -0,0 +1,39 @@
+/* Audit module for tst-audit11.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+  return version;
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+  if (strcmp (name, "tst-audit11mod2.so") == 0)
+    {
+      return (char *) "$ORIGIN/tst-audit11mod2.so";
+    }
+  return (char *) name;
+}
diff --git a/REORG.TODO/elf/tst-auditmod12.c b/REORG.TODO/elf/tst-auditmod12.c
new file mode 100644
index 0000000000..039b7cd62b
--- /dev/null
+++ b/REORG.TODO/elf/tst-auditmod12.c
@@ -0,0 +1,43 @@
+/* Audit module for tst-audit12.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+  return version;
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+  const char target[] = "tst-audit12mod2.so";
+
+  size_t namelen = strlen (name);
+  if (namelen >= sizeof (target) - 1
+      && strcmp (name + namelen - (sizeof (target) - 1), target) == 0)
+    {
+      return (char *) "$ORIGIN/tst-audit12mod3.so";
+    }
+  return (char *) name;
+}
diff --git a/REORG.TODO/elf/tst-auditmod9a.c b/REORG.TODO/elf/tst-auditmod9a.c
new file mode 100644
index 0000000000..7213ade123
--- /dev/null
+++ b/REORG.TODO/elf/tst-auditmod9a.c
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+__thread int var;
+
+unsigned int
+la_version (unsigned int v)
+{
+  return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+  ++var;
+}
diff --git a/REORG.TODO/elf/tst-auditmod9b.c b/REORG.TODO/elf/tst-auditmod9b.c
new file mode 100644
index 0000000000..8eeeb49986
--- /dev/null
+++ b/REORG.TODO/elf/tst-auditmod9b.c
@@ -0,0 +1,6 @@
+__thread int a;
+
+int f(void)
+{
+  return ++a;
+}
diff --git a/REORG.TODO/elf/tst-auxv.c b/REORG.TODO/elf/tst-auxv.c
new file mode 100644
index 0000000000..bc571c5fa7
--- /dev/null
+++ b/REORG.TODO/elf/tst-auxv.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <errno.h>
+#include <link.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <misc/sys/auxv.h>
+
+static int
+do_test (int argc, char *argv[])
+{
+  errno = 0;
+  const char *execfn = (const char *) getauxval (AT_NULL);
+
+  if (errno != ENOENT)
+    {
+      printf ("errno is %d rather than %d (ENOENT) on failure\n", errno,
+	      ENOENT);
+      return 1;
+    }
+
+  if (execfn != NULL)
+    {
+      printf ("getauxval return value is nonzero on failure\n");
+      return 1;
+    }
+
+  errno = 0;
+  execfn = (const char *) getauxval (AT_EXECFN);
+
+  if (execfn == NULL)
+    {
+      printf ("No AT_EXECFN found, AT_EXECFN test skipped\n");
+      return 0;
+    }
+
+  if (errno != 0)
+    {
+      printf ("errno erroneously set to %d on success\n", errno);
+      return 1;
+    }
+
+  if (strcmp (argv[0], execfn) != 0)
+    {
+      printf ("Mismatch: argv[0]: %s vs. AT_EXECFN: %s\n", argv[0], execfn);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-deep1.c b/REORG.TODO/elf/tst-deep1.c
new file mode 100644
index 0000000000..97dce7ea4d
--- /dev/null
+++ b/REORG.TODO/elf/tst-deep1.c
@@ -0,0 +1,35 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+xyzzy (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return 21;
+}
+
+int
+back (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return 1;
+}
+
+extern int foo (void);
+
+static int
+do_test (void)
+{
+  void *p = dlopen ("$ORIGIN/tst-deep1mod2.so", RTLD_LAZY|RTLD_DEEPBIND);
+
+  int (*f) (void) = dlsym (p, "bar");
+  if (f == NULL)
+    {
+      puts (dlerror ());
+      return 1;
+    }
+
+  return foo () + f ();
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-deep1mod1.c b/REORG.TODO/elf/tst-deep1mod1.c
new file mode 100644
index 0000000000..cc922e6ea5
--- /dev/null
+++ b/REORG.TODO/elf/tst-deep1mod1.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+int
+foo (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return 1;
+}
+
+int
+baz (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return 20;
+}
diff --git a/REORG.TODO/elf/tst-deep1mod2.c b/REORG.TODO/elf/tst-deep1mod2.c
new file mode 100644
index 0000000000..b99caf0328
--- /dev/null
+++ b/REORG.TODO/elf/tst-deep1mod2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+extern int baz (void);
+extern int xyzzy (void);
+int
+bar (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return baz () + xyzzy ();;
+}
+
+int
+back (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return -1;
+}
diff --git a/REORG.TODO/elf/tst-deep1mod3.c b/REORG.TODO/elf/tst-deep1mod3.c
new file mode 100644
index 0000000000..eee7d5c97b
--- /dev/null
+++ b/REORG.TODO/elf/tst-deep1mod3.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+extern int back (void);
+
+int
+baz (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return back ();
+}
+
+int
+xyzzy (void)
+{
+  printf ("%s:%s\n", __FILE__, __func__);
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-dl-iter-static.c b/REORG.TODO/elf/tst-dl-iter-static.c
new file mode 100644
index 0000000000..9a2758c8ef
--- /dev/null
+++ b/REORG.TODO/elf/tst-dl-iter-static.c
@@ -0,0 +1,46 @@
+/* BZ #16046 dl_iterate_phdr static executable test.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+
+/* Check that the link map of the static executable itself is iterated
+   over exactly once.  */
+
+static int
+callback (struct dl_phdr_info *info, size_t size, void *data)
+{
+  int *count = data;
+
+  if (info->dlpi_name[0] == '\0')
+    (*count)++;
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  int count = 0;
+  int status;
+
+  status = dl_iterate_phdr (callback, &count);
+
+  return status || count != 1;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlmodcount.c b/REORG.TODO/elf/tst-dlmodcount.c
new file mode 100644
index 0000000000..34c5b25d7f
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlmodcount.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David Mosberger <davidm@hpl.hp.com>, 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define SET	0
+#define ADD	1
+#define REMOVE	2
+
+#define leq(l,r)	(((r) - (l)) <= ~0ULL / 2)
+
+static int
+callback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+  static int last_adds = 0, last_subs = 0;
+  intptr_t cmd = (intptr_t) ptr;
+
+  printf ("  size = %Zu\n", size);
+  if (size < (offsetof (struct dl_phdr_info, dlpi_subs)
+	      + sizeof (info->dlpi_subs)))
+    {
+      fprintf (stderr, "dl_iterate_phdr failed to pass dlpi_adds/dlpi_subs\n");
+      exit (5);
+    }
+
+  printf ("  dlpi_adds = %Lu dlpi_subs = %Lu\n",
+	  info->dlpi_adds, info->dlpi_subs);
+
+  switch (cmd)
+    {
+    case SET:
+      break;
+
+    case ADD:
+      if (leq (info->dlpi_adds, last_adds))
+	{
+	  fprintf (stderr, "dlpi_adds failed to get incremented!\n");
+	  exit (3);
+	}
+      break;
+
+    case REMOVE:
+      if (leq (info->dlpi_subs, last_subs))
+	{
+	  fprintf (stderr, "dlpi_subs failed to get incremented!\n");
+	  exit (4);
+	}
+      break;
+    }
+  last_adds = info->dlpi_adds;
+  last_subs = info->dlpi_subs;
+  return -1;
+}
+
+static void *
+load (const char *path)
+{
+  void *handle;
+
+  printf ("loading `%s'\n", path);
+  handle = dlopen (path, RTLD_LAZY);
+  if (!handle)
+    exit (1);
+  dl_iterate_phdr (callback, (void *)(intptr_t) ADD);
+  return handle;
+}
+
+static void
+unload (const char *path, void *handle)
+{
+  printf ("unloading `%s'\n", path);
+  if (dlclose (handle) < 0)
+    exit (2);
+  dl_iterate_phdr (callback, (void *)(intptr_t) REMOVE);
+}
+
+static int
+do_test (void)
+{
+  void *handle1, *handle2;
+
+  dl_iterate_phdr (callback, (void *)(intptr_t) SET);
+  handle1 = load ("firstobj.so");
+  handle2 = load ("globalmod1.so");
+  unload ("firstobj.so", handle1);
+  unload ("globalmod1.so", handle2);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlmopen1.c b/REORG.TODO/elf/tst-dlmopen1.c
new file mode 100644
index 0000000000..24145cfca6
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlmopen1.c
@@ -0,0 +1,80 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <gnu/lib-names.h>
+
+#define TEST_SO "$ORIGIN/tst-dlmopen1mod.so"
+
+static int
+do_test (void)
+{
+  void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD);
+  if (h == NULL)
+    {
+      printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ());
+      return 1;
+    }
+
+  Lmid_t ns = -10;
+  if (dlinfo (h, RTLD_DI_LMID, &ns) != 0)
+    {
+      printf ("dlinfo for %s in %s failed: %s\n",
+	      LIBC_SO, __func__, dlerror ());
+      return 1;
+    }
+
+  if (ns != LM_ID_BASE)
+    {
+      printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO);
+      return 1;
+    }
+
+  if (dlclose (h) != 0)
+    {
+      printf ("dlclose for %s in %s failed: %s\n",
+	      LIBC_SO, __func__, dlerror ());
+      return 1;
+    }
+
+  h = dlmopen (LM_ID_NEWLM, TEST_SO, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot get handle for %s: %s\n",
+	      "tst-dlmopen1mod.so", dlerror ());
+      return 1;
+    }
+
+  ns = -10;
+  if (dlinfo (h, RTLD_DI_LMID, &ns) != 0)
+    {
+      printf ("dlinfo for %s in %s failed: %s\n",
+	      "tst-dlmopen1mod.so", __func__, dlerror ());
+      return 1;
+    }
+
+  if (ns == LM_ID_BASE)
+    {
+      printf ("namespace for %s is LM_ID_BASE\n", TEST_SO);
+      return 1;
+    }
+
+  int (*fct) (Lmid_t) = dlsym (h, "foo");
+  if (fct == NULL)
+    {
+      printf ("could not find %s: %s\n", "foo", dlerror ());
+      return 1;
+    }
+
+  if (fct (ns) != 0)
+    return 1;
+
+  if (dlclose (h) != 0)
+    {
+      printf ("dlclose for %s in %s failed: %s\n",
+	      TEST_SO, __func__, dlerror ());
+      return 1;
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlmopen1mod.c b/REORG.TODO/elf/tst-dlmopen1mod.c
new file mode 100644
index 0000000000..142488098a
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlmopen1mod.c
@@ -0,0 +1,59 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <gnu/lib-names.h>
+
+
+static int cnt;
+
+static void
+__attribute ((constructor))
+constr (void)
+{
+  ++cnt;
+}
+
+
+int
+foo (Lmid_t ns2)
+{
+  void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD);
+  if (h == NULL)
+    {
+      printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ());
+      return 1;
+    }
+
+  Lmid_t ns = -10;
+  if (dlinfo (h, RTLD_DI_LMID, &ns) != 0)
+    {
+      printf ("dlinfo for %s in %s failed: %s\n",
+	      LIBC_SO, __func__, dlerror ());
+      return 1;
+    }
+
+  if (ns != ns2)
+    {
+      printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO);
+      return 1;
+    }
+
+  if (dlclose (h) != 0)
+    {
+      printf ("dlclose for %s in %s failed: %s\n",
+	      LIBC_SO, __func__, dlerror ());
+      return 1;
+    }
+
+  if (cnt == 0)
+    {
+      puts ("constructor did not run");
+      return 1;
+    }
+  else if (cnt != 1)
+    {
+      puts ("constructor did not run exactly once");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-dlmopen2.c b/REORG.TODO/elf/tst-dlmopen2.c
new file mode 100644
index 0000000000..8489ffba08
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlmopen2.c
@@ -0,0 +1,69 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <gnu/lib-names.h>
+#include <ldsodefs.h>
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  for (int i = 1; i <= 10; ++i)
+    {
+      void *h[DL_NNS - 1];
+      char used[DL_NNS];
+
+      printf ("round %d\n", i);
+
+      memset (used, '\0', sizeof (used));
+      used[LM_ID_BASE] = 1;
+
+      for (int j = 0; j < DL_NNS - 1; ++j)
+	{
+	  h[j] = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so",
+			  RTLD_LAZY);
+	  if (h[j] == NULL)
+	    {
+	      printf ("round %d, namespace %d: load failed: %s\n",
+		      i, j, dlerror ());
+	      return 1;
+	    }
+	  Lmid_t ns;
+	  if (dlinfo (h[j], RTLD_DI_LMID, &ns) != 0)
+	    {
+	      printf ("round %d, namespace %d: dlinfo failed: %s\n",
+		      i, j, dlerror ());
+	      return 1;
+	    }
+	  if (ns < 0 || ns >= DL_NNS)
+	    {
+	      printf ("round %d, namespace %d: invalid namespace %ld",
+		      i, j, (long int) ns);
+	      result = 1;
+	    }
+	  else if (used[ns] != 0)
+	    {
+	      printf ("\
+round %d, namespace %d: duplicate allocate of namespace %ld",
+		      i, j, (long int) ns);
+	      result = 1;
+	    }
+	  else
+	    used[ns] = 1;
+	}
+
+      for (int j = 0; j < DL_NNS - 1; ++j)
+	if (dlclose (h[j]) != 0)
+	  {
+	    printf ("round %d, namespace %d: close failed: %s\n",
+		    i, j, dlerror ());
+	    return 1;
+	  }
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlmopen3.c b/REORG.TODO/elf/tst-dlmopen3.c
new file mode 100644
index 0000000000..8167507784
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlmopen3.c
@@ -0,0 +1,21 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+  void *h = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot get handle for %s: %s\n",
+	      "tst-dlmopen1mod.so", dlerror ());
+      return 1;
+    }
+
+  /* Do not unload.  */
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlopen-aout.c b/REORG.TODO/elf/tst-dlopen-aout.c
new file mode 100644
index 0000000000..cccc508966
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlopen-aout.c
@@ -0,0 +1,67 @@
+/* Test case for BZ #16634.
+
+   Verify that incorrectly dlopen()ing an executable without
+   __RTLD_OPENEXEC does not cause assertion in ld.so.
+
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.
+
+   Note: this test currently only fails when glibc is configured with
+   --enable-hardcoded-path-in-tests.  */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <pthread.h>
+
+__thread int x;
+
+void *
+fn (void *p)
+{
+  return p;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  int j;
+
+  for (j = 0; j < 100; ++j)
+    {
+      pthread_t thr;
+      void *p;
+      int rc;
+
+      p = dlopen (argv[0], RTLD_LAZY);
+      if (p != NULL)
+        {
+          fprintf (stderr, "dlopen unexpectedly succeeded\n");
+          return 1;
+        }
+      rc = pthread_create (&thr, NULL, fn, NULL);
+      assert (rc == 0);
+
+      rc = pthread_join (thr, NULL);
+      assert (rc == 0);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlopenrpath.c b/REORG.TODO/elf/tst-dlopenrpath.c
new file mode 100644
index 0000000000..77346d36f9
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlopenrpath.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+extern int foo (void);
+
+static const char testsubdir[] = PFX "test-subdir";
+
+
+static int
+do_test (void)
+{
+  struct stat64 st;
+  int result = 1;
+
+  if (mkdir (testsubdir, 0777) != 0
+      && (errno != EEXIST
+	  || stat64 (testsubdir, &st) != 0
+	  || !S_ISDIR (st.st_mode)))
+    {
+      printf ("cannot create directory %s\n", testsubdir);
+      return 1;
+    }
+
+  if (system ("cp " PFX "firstobj.so " PFX "test-subdir/in-subdir.so") != 0)
+    {
+      puts ("cannot copy DSO");
+      return 1;
+    }
+
+  void *p = dlopen ("in-subdir.so", RTLD_LAZY|RTLD_LOCAL);
+  if (p != NULL)
+    {
+      puts ("succeeded in opening in-subdir.so from do_test");
+      dlclose (p);
+      goto out;
+    }
+
+  result = foo ();
+
+ out:
+  unlink (PFX "test-subdir/in-subdir.so");
+  rmdir (testsubdir);
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-dlopenrpathmod.c b/REORG.TODO/elf/tst-dlopenrpathmod.c
new file mode 100644
index 0000000000..6d244401bf
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlopenrpathmod.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+int
+foo (void)
+{
+  void *p = dlopen ("in-subdir.so", RTLD_LAZY|RTLD_LOCAL);
+  if (p != NULL)
+    {
+      dlclose (p);
+      return 0;
+    }
+
+  puts ("couldn't open in-subdir.so from foo");
+  return 1;
+}
diff --git a/REORG.TODO/elf/tst-dlsym-error.c b/REORG.TODO/elf/tst-dlsym-error.c
new file mode 100644
index 0000000000..fac8f10ccf
--- /dev/null
+++ b/REORG.TODO/elf/tst-dlsym-error.c
@@ -0,0 +1,113 @@
+/* Test error reporting for dlsym, dlvsym failures.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <gnu/lib-names.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Used to disambiguate symbol names.  */
+static int counter;
+
+static void
+test_one (void *handle, const char *name, void *(func) (void *, const char *),
+          const char *suffix)
+{
+  ++counter;
+  char symbol[32];
+  snprintf (symbol, sizeof (symbol), "no_such_symbol_%d", counter);
+  char *expected_message;
+  if (asprintf (&expected_message, ": undefined symbol: %s%s",
+                symbol, suffix) < 0)
+    {
+      printf ("error: asprintf: %m\n");
+      abort ();
+    }
+
+  void *addr = func (handle, symbol);
+  if (addr != NULL)
+    {
+      printf ("error: %s: found symbol \"no_such_symbol\"\n", name);
+      abort ();
+    }
+  const char *message = dlerror ();
+  if (message == NULL)
+    {
+      printf ("error: %s: missing error message\n", name);
+      abort ();
+    }
+  const char *message_without_path = strchrnul (message, ':');
+  if (strcmp (message_without_path, expected_message) != 0)
+    {
+      printf ("error: %s: unexpected error message: %s\n", name, message);
+      abort ();
+    }
+  free (expected_message);
+
+  message = dlerror ();
+  if (message != NULL)
+    {
+      printf ("error: %s: unexpected error message: %s\n", name, message);
+      abort ();
+    }
+}
+
+static void
+test_handles (const char *name, void *(func) (void *, const char *),
+              const char *suffix)
+{
+  test_one (RTLD_DEFAULT, name, func, suffix);
+  test_one (RTLD_NEXT, name, func, suffix);
+
+  void *handle = dlopen (LIBC_SO, RTLD_LAZY);
+  if (handle == NULL)
+    {
+      printf ("error: cannot dlopen %s: %s\n", LIBC_SO, dlerror ());
+      abort ();
+    }
+  test_one (handle, name, func, suffix);
+  dlclose (handle);
+}
+
+static void *
+dlvsym_no_such_version (void *handle, const char *name)
+{
+  return dlvsym (handle, name, "NO_SUCH_VERSION");
+}
+
+static void *
+dlvsym_glibc_private (void *handle, const char *name)
+{
+  return dlvsym (handle, name, "GLIBC_PRIVATE");
+}
+
+static int
+do_test (void)
+{
+  test_handles ("dlsym", dlsym, "");
+  test_handles ("dlvsym", dlvsym_no_such_version,
+                ", version NO_SUCH_VERSION");
+  test_handles ("dlvsym", dlvsym_glibc_private,
+                ", version GLIBC_PRIVATE");
+
+  return 0;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-env-setuid-tunables.c b/REORG.TODO/elf/tst-env-setuid-tunables.c
new file mode 100644
index 0000000000..afcb146e6d
--- /dev/null
+++ b/REORG.TODO/elf/tst-env-setuid-tunables.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Verify that tunables correctly filter out unsafe tunables like
+   glibc.malloc.check and glibc.malloc.mmap_threshold but also retain
+   glibc.malloc.mmap_threshold in an unprivileged child.  */
+
+/* This is compiled as part of the testsuite but needs to see
+   HAVE_TUNABLES. */
+#define _LIBC 1
+#include "config.h"
+#undef _LIBC
+
+#define test_parent test_parent_tunables
+#define test_child test_child_tunables
+
+static int test_child_tunables (void);
+static int test_parent_tunables (void);
+
+#include "tst-env-setuid.c"
+
+#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096"
+#define PARENT_VALSTRING_VALUE \
+  "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096"
+
+static int
+test_child_tunables (void)
+{
+  const char *val = getenv ("GLIBC_TUNABLES");
+
+#if HAVE_TUNABLES
+  if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0)
+    return 0;
+
+  if (val != NULL)
+    printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
+
+  return 1;
+#else
+  if (val != NULL)
+    {
+      printf ("GLIBC_TUNABLES not cleared\n");
+      return 1;
+    }
+  return 0;
+#endif
+}
+
+static int
+test_parent_tunables (void)
+{
+  const char *val = getenv ("GLIBC_TUNABLES");
+
+  if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0)
+    return 0;
+
+  if (val != NULL)
+    printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
+
+  return 1;
+}
diff --git a/REORG.TODO/elf/tst-env-setuid.c b/REORG.TODO/elf/tst-env-setuid.c
new file mode 100644
index 0000000000..eec408eb5d
--- /dev/null
+++ b/REORG.TODO/elf/tst-env-setuid.c
@@ -0,0 +1,296 @@
+/* Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Verify that tunables correctly filter out unsafe environment variables like
+   MALLOC_CHECK_ and MALLOC_MMAP_THRESHOLD_ but also retain
+   MALLOC_MMAP_THRESHOLD_ in an unprivileged child.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <support/support.h>
+#include <support/test-driver.h>
+
+static char SETGID_CHILD[] = "setgid-child";
+#define CHILD_STATUS 42
+
+/* Return a GID which is not our current GID, but is present in the
+   supplementary group list.  */
+static gid_t
+choose_gid (void)
+{
+  const int count = 64;
+  gid_t groups[count];
+  int ret = getgroups (count, groups);
+  if (ret < 0)
+    {
+      printf ("getgroups: %m\n");
+      exit (1);
+    }
+  gid_t current = getgid ();
+  for (int i = 0; i < ret; ++i)
+    {
+      if (groups[i] != current)
+	return groups[i];
+    }
+  return 0;
+}
+
+/* Spawn and execute a program and verify that it returns the CHILD_STATUS.  */
+static pid_t
+do_execve (char **args)
+{
+  pid_t kid = vfork ();
+
+  if (kid < 0)
+    {
+      printf ("vfork: %m\n");
+      return -1;
+    }
+
+  if (kid == 0)
+    {
+      /* Child process.  */
+      execve (args[0], args, environ);
+      _exit (-errno);
+    }
+
+  if (kid < 0)
+    return 1;
+
+  int status;
+
+  if (waitpid (kid, &status, 0) < 0)
+    {
+      printf ("waitpid: %m\n");
+      return 1;
+    }
+
+  if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
+    return EXIT_UNSUPPORTED;
+
+  if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS)
+    {
+      printf ("Unexpected exit status %d from child process\n",
+	      WEXITSTATUS (status));
+      return 1;
+    }
+  return 0;
+}
+
+/* Copies the executable into a restricted directory, so that we can
+   safely make it SGID with the TARGET group ID.  Then runs the
+   executable.  */
+static int
+run_executable_sgid (gid_t target)
+{
+  char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd",
+			     test_dir, (intmax_t) getpid ());
+  char *execname = xasprintf ("%s/bin", dirname);
+  int infd = -1;
+  int outfd = -1;
+  int ret = 0;
+  if (mkdir (dirname, 0700) < 0)
+    {
+      printf ("mkdir: %m\n");
+      goto err;
+    }
+  infd = open ("/proc/self/exe", O_RDONLY);
+  if (infd < 0)
+    {
+      printf ("open (/proc/self/exe): %m\n");
+      goto err;
+    }
+  outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
+  if (outfd < 0)
+    {
+      printf ("open (%s): %m\n", execname);
+      goto err;
+    }
+  char buf[4096];
+  for (;;)
+    {
+      ssize_t rdcount = read (infd, buf, sizeof (buf));
+      if (rdcount < 0)
+	{
+	  printf ("read: %m\n");
+	  goto err;
+	}
+      if (rdcount == 0)
+	break;
+      char *p = buf;
+      char *end = buf + rdcount;
+      while (p != end)
+	{
+	  ssize_t wrcount = write (outfd, buf, end - p);
+	  if (wrcount == 0)
+	    errno = ENOSPC;
+	  if (wrcount <= 0)
+	    {
+	      printf ("write: %m\n");
+	      goto err;
+	    }
+	  p += wrcount;
+	}
+    }
+  if (fchown (outfd, getuid (), target) < 0)
+    {
+      printf ("fchown (%s): %m\n", execname);
+      goto err;
+    }
+  if (fchmod (outfd, 02750) < 0)
+    {
+      printf ("fchmod (%s): %m\n", execname);
+      goto err;
+    }
+  if (close (outfd) < 0)
+    {
+      printf ("close (outfd): %m\n");
+      goto err;
+    }
+  if (close (infd) < 0)
+    {
+      printf ("close (infd): %m\n");
+      goto err;
+    }
+
+  char *args[] = {execname, SETGID_CHILD, NULL};
+
+  ret = do_execve (args);
+
+err:
+  if (outfd >= 0)
+    close (outfd);
+  if (infd >= 0)
+    close (infd);
+  if (execname)
+    {
+      unlink (execname);
+      free (execname);
+    }
+  if (dirname)
+    {
+      rmdir (dirname);
+      free (dirname);
+    }
+  return ret;
+}
+
+#ifndef test_child
+static int
+test_child (void)
+{
+  if (getenv ("MALLOC_CHECK_") != NULL)
+    {
+      printf ("MALLOC_CHECK_ is still set\n");
+      return 1;
+    }
+
+  if (getenv ("MALLOC_MMAP_THRESHOLD_") == NULL)
+    {
+      printf ("MALLOC_MMAP_THRESHOLD_ lost\n");
+      return 1;
+    }
+
+  if (getenv ("LD_HWCAP_MASK") != NULL)
+    {
+      printf ("LD_HWCAP_MASK still set\n");
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
+#ifndef test_parent
+static int
+test_parent (void)
+{
+  if (getenv ("MALLOC_CHECK_") == NULL)
+    {
+      printf ("MALLOC_CHECK_ lost\n");
+      return 1;
+    }
+
+  if (getenv ("MALLOC_MMAP_THRESHOLD_") == NULL)
+    {
+      printf ("MALLOC_MMAP_THRESHOLD_ lost\n");
+      return 1;
+    }
+
+  if (getenv ("LD_HWCAP_MASK") == NULL)
+    {
+      printf ("LD_HWCAP_MASK lost\n");
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
+static int
+do_test (int argc, char **argv)
+{
+  /* Setgid child process.  */
+  if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
+    {
+      if (getgid () == getegid ())
+	{
+	  /* This can happen if the file system is mounted nosuid.  */
+	  fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
+		   (intmax_t) getgid ());
+	  exit (EXIT_UNSUPPORTED);
+	}
+
+      int ret = test_child ();
+
+      if (ret != 0)
+	exit (1);
+
+      exit (CHILD_STATUS);
+    }
+  else
+    {
+      if (test_parent () != 0)
+	exit (1);
+
+      /* Try running a setgid program.  */
+      gid_t target = choose_gid ();
+      if (target == 0)
+	{
+	  fprintf (stderr,
+		   "Could not find a suitable GID for user %jd, skipping test\n",
+		   (intmax_t) getuid ());
+	  exit (0);
+	}
+
+      return run_executable_sgid (target);
+    }
+
+  /* Something went wrong and our argv was corrupted.  */
+  _exit (1);
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-execstack-mod.c b/REORG.TODO/elf/tst-execstack-mod.c
new file mode 100644
index 0000000000..038e6550b5
--- /dev/null
+++ b/REORG.TODO/elf/tst-execstack-mod.c
@@ -0,0 +1,30 @@
+/* Test module for making nonexecutable stacks executable
+   on load of a DSO that requires executable stacks.  */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void callme (void (*callback) (void));
+
+/* This is a function that makes use of executable stack by
+   using a local function trampoline.  */
+void
+tryme (void)
+{
+  bool ok = false;
+  void callback (void) { ok = true; }
+
+  callme (&callback);
+
+  if (ok)
+    printf ("DSO called ok (local %p, trampoline %p)\n", &ok, &callback);
+  else
+    abort ();
+}
+
+void
+callme (void (*callback) (void))
+{
+  (*callback) ();
+}
diff --git a/REORG.TODO/elf/tst-execstack-needed.c b/REORG.TODO/elf/tst-execstack-needed.c
new file mode 100644
index 0000000000..8b794a3d47
--- /dev/null
+++ b/REORG.TODO/elf/tst-execstack-needed.c
@@ -0,0 +1,34 @@
+/* Test program for making nonexecutable stacks executable
+   on DT_NEEDED load of a DSO that requires executable stacks.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <error.h>
+
+extern void tryme (void);	/* from tst-execstack-mod.so */
+
+static void deeper (void (*f) (void));
+
+static int
+do_test (void)
+{
+  tryme ();
+
+  /* Test that growing the stack region gets new executable pages too.  */
+  deeper (&tryme);
+
+  return 0;
+}
+
+static void
+deeper (void (*f) (void))
+{
+  char stack[1100 * 1024];
+  memfrob (stack, sizeof stack);
+  (*f) ();
+  memfrob (stack, sizeof stack);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-execstack-prog.c b/REORG.TODO/elf/tst-execstack-prog.c
new file mode 100644
index 0000000000..8663153372
--- /dev/null
+++ b/REORG.TODO/elf/tst-execstack-prog.c
@@ -0,0 +1,33 @@
+/* Test program for executable stacks in an executable itself.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <error.h>
+
+#include "tst-execstack-mod.c"	/* This defines the `tryme' test function.  */
+
+static void deeper (void (*f) (void));
+
+static int
+do_test (void)
+{
+  tryme ();
+
+  /* Test that growing the stack region gets new executable pages too.  */
+  deeper (&tryme);
+
+  return 0;
+}
+
+static void
+deeper (void (*f) (void))
+{
+  char stack[1100 * 1024];
+  memfrob (stack, sizeof stack);
+  (*f) ();
+  memfrob (stack, sizeof stack);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-execstack.c b/REORG.TODO/elf/tst-execstack.c
new file mode 100644
index 0000000000..114f341d76
--- /dev/null
+++ b/REORG.TODO/elf/tst-execstack.c
@@ -0,0 +1,236 @@
+/* Test program for making nonexecutable stacks executable
+   on load of a DSO that requires executable stacks.  */
+
+#include <dlfcn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <error.h>
+#include <stackinfo.h>
+
+static void
+print_maps (void)
+{
+#if 0
+  char *cmd = NULL;
+  asprintf (&cmd, "cat /proc/%d/maps", getpid ());
+  system (cmd);
+  free (cmd);
+#endif
+}
+
+static void deeper (void (*f) (void));
+
+#if USE_PTHREADS
+# include <pthread.h>
+
+static void *
+tryme_thread (void *f)
+{
+  (*((void (*) (void)) f)) ();
+
+  return 0;
+}
+
+static pthread_barrier_t startup_barrier, go_barrier;
+static void *
+waiter_thread (void *arg)
+{
+  void **f = arg;
+  pthread_barrier_wait (&startup_barrier);
+  pthread_barrier_wait (&go_barrier);
+
+  (*((void (*) (void)) *f)) ();
+
+  return 0;
+}
+#endif
+
+static bool allow_execstack = true;
+
+
+static int
+do_test (void)
+{
+  /* Check whether SELinux is enabled and disallows executable stacks.  */
+  FILE *fp = fopen ("/selinux/enforce", "r");
+  if (fp != NULL)
+    {
+      char *line = NULL;
+      size_t linelen = 0;
+
+      bool enabled = false;
+      ssize_t n = getline (&line, &linelen, fp);
+      if (n > 0 && line[0] != '0')
+	enabled = true;
+
+      fclose (fp);
+
+      if (enabled)
+	{
+	  fp = fopen ("/selinux/booleans/allow_execstack", "r");
+	  if (fp != NULL)
+	    {
+	      n = getline (&line, &linelen, fp);
+	      if (n > 0 && line[0] == '0')
+		allow_execstack = false;
+	    }
+
+	  fclose (fp);
+	}
+    }
+
+  printf ("executable stacks %sallowed\n", allow_execstack ? "" : "not ");
+
+  static void *f;		/* Address of this is used in other threads. */
+
+#if USE_PTHREADS
+  /* Create some threads while stacks are nonexecutable.  */
+  #define N 5
+  pthread_t thr[N];
+
+  pthread_barrier_init (&startup_barrier, NULL, N + 1);
+  pthread_barrier_init (&go_barrier, NULL, N + 1);
+
+  for (int i = 0; i < N; ++i)
+    {
+      int rc = pthread_create (&thr[i], NULL, &waiter_thread, &f);
+      if (rc)
+	error (1, rc, "pthread_create");
+    }
+
+  /* Make sure they are all there using their stacks.  */
+  pthread_barrier_wait (&startup_barrier);
+  puts ("threads waiting");
+#endif
+
+  print_maps ();
+
+#if USE_PTHREADS
+  void *old_stack_addr, *new_stack_addr;
+  size_t stack_size;
+  pthread_t me = pthread_self ();
+  pthread_attr_t attr;
+  int ret = 0;
+
+  ret = pthread_getattr_np (me, &attr);
+  if (ret)
+    {
+      printf ("before execstack: pthread_getattr_np returned error: %s\n",
+	      strerror (ret));
+      return 1;
+    }
+
+  ret = pthread_attr_getstack (&attr, &old_stack_addr, &stack_size);
+  if (ret)
+    {
+      printf ("before execstack: pthread_attr_getstack returned error: %s\n",
+	      strerror (ret));
+      return 1;
+    }
+# if _STACK_GROWS_DOWN
+    old_stack_addr += stack_size;
+# else
+    old_stack_addr -= stack_size;
+# endif
+#endif
+
+  /* Loading this module should force stacks to become executable.  */
+  void *h = dlopen ("tst-execstack-mod.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot load: %s\n", dlerror ());
+      return allow_execstack;
+    }
+
+  f = dlsym (h, "tryme");
+  if (f == NULL)
+    {
+      printf ("symbol not found: %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Test if that really made our stack executable.
+     The `tryme' function should crash if not.  */
+
+  (*((void (*) (void)) f)) ();
+
+  print_maps ();
+
+#if USE_PTHREADS
+  ret = pthread_getattr_np (me, &attr);
+  if (ret)
+    {
+      printf ("after execstack: pthread_getattr_np returned error: %s\n",
+	      strerror (ret));
+      return 1;
+    }
+
+  ret = pthread_attr_getstack (&attr, &new_stack_addr, &stack_size);
+  if (ret)
+    {
+      printf ("after execstack: pthread_attr_getstack returned error: %s\n",
+	      strerror (ret));
+      return 1;
+    }
+
+# if _STACK_GROWS_DOWN
+    new_stack_addr += stack_size;
+# else
+    new_stack_addr -= stack_size;
+# endif
+
+  /* It is possible that the dlopen'd module may have been mmapped just below
+     the stack.  The stack size is taken as MIN(stack rlimit size, end of last
+     vma) in pthread_getattr_np.  If rlimit is set high enough, it is possible
+     that the size may have changed.  A subsequent call to
+     pthread_attr_getstack returns the size and (bottom - size) as the
+     stacksize and stackaddr respectively.  If the size changes due to the
+     above, then both stacksize and stackaddr can change, but the stack bottom
+     should remain the same, which is computed as stackaddr + stacksize.  */
+  if (old_stack_addr != new_stack_addr)
+    {
+      printf ("Stack end changed, old: %p, new: %p\n",
+	      old_stack_addr, new_stack_addr);
+      return 1;
+    }
+  printf ("Stack address remains the same: %p\n", old_stack_addr);
+#endif
+
+  /* Test that growing the stack region gets new executable pages too.  */
+  deeper ((void (*) (void)) f);
+
+  print_maps ();
+
+#if USE_PTHREADS
+  /* Test that a fresh thread now gets an executable stack.  */
+  {
+    pthread_t th;
+    int rc = pthread_create (&th, NULL, &tryme_thread, f);
+    if (rc)
+      error (1, rc, "pthread_create");
+  }
+
+  puts ("threads go");
+  /* The existing threads' stacks should have been changed.
+     Let them run to test it.  */
+  pthread_barrier_wait (&go_barrier);
+
+  pthread_exit ((void *) (long int) (! allow_execstack));
+#endif
+
+  return ! allow_execstack;
+}
+
+static void
+deeper (void (*f) (void))
+{
+  char stack[1100 * 1024];
+  memfrob (stack, sizeof stack);
+  (*f) ();
+  memfrob (stack, sizeof stack);
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-global1.c b/REORG.TODO/elf/tst-global1.c
new file mode 100644
index 0000000000..5dae74eec0
--- /dev/null
+++ b/REORG.TODO/elf/tst-global1.c
@@ -0,0 +1,38 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h1 = dlopen ("$ORIGIN/testobj6.so", RTLD_GLOBAL|RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      puts ("cannot open testobj6");
+      return 1;
+    }
+
+  void *h2 = dlopen ("$ORIGIN/testobj2.so",
+		     RTLD_GLOBAL|RTLD_DEEPBIND|RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("cannot open testobj2");
+      return 1;
+    }
+
+  dlclose (h1);
+
+  void (*f) (void) = dlsym (h2, "p");
+  if (f == NULL)
+    {
+      puts ("cannot find p");
+      return 1;
+    }
+
+  f ();
+
+  dlclose (h2);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-gnu2-tls1.c b/REORG.TODO/elf/tst-gnu2-tls1.c
new file mode 100644
index 0000000000..b33b60a301
--- /dev/null
+++ b/REORG.TODO/elf/tst-gnu2-tls1.c
@@ -0,0 +1,51 @@
+/* Test local and global dynamic models for GNU2 TLS.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int * get_gd (void);
+extern void set_gd (int);
+extern int test_gd (int);
+extern int * get_ld (void);
+extern void set_ld (int);
+extern int test_ld (int);
+
+__thread int gd = 1;
+
+static int
+do_test (void)
+{
+  int *p;
+
+  p = get_gd ();
+  set_gd (3);
+  if (*p != 3 || !test_gd (3))
+    abort ();
+
+  p = get_ld ();
+  set_ld (4);
+  if (*p != 4 || !test_ld (4))
+    abort ();
+
+  printf ("PASS\n");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-gnu2-tls1mod.c b/REORG.TODO/elf/tst-gnu2-tls1mod.c
new file mode 100644
index 0000000000..fa76ab1222
--- /dev/null
+++ b/REORG.TODO/elf/tst-gnu2-tls1mod.c
@@ -0,0 +1,56 @@
+/* DSO used by tst-gnu2-tls1.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+static __thread int ld;
+
+int *
+get_ld (void)
+{
+  return &ld;
+}
+
+void
+set_ld (int i)
+{
+  ld = i;
+}
+
+int
+test_ld (int i)
+{
+  return ld == i;
+}
+extern __thread int gd;
+
+int *
+get_gd (void)
+{
+  return &gd;
+}
+
+void
+set_gd (int i)
+{
+  gd = i;
+}
+
+int
+test_gd (int i)
+{
+  return gd == i;
+}
diff --git a/REORG.TODO/elf/tst-initorder.c b/REORG.TODO/elf/tst-initorder.c
new file mode 100644
index 0000000000..9638382104
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorder.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int
+main( int argc, char *argv[] )
+{
+  printf( "main\n" );
+}
diff --git a/REORG.TODO/elf/tst-initorder.exp b/REORG.TODO/elf/tst-initorder.exp
new file mode 100644
index 0000000000..8718f65765
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorder.exp
@@ -0,0 +1,13 @@
+start_a1
+start_a2
+start_b1
+start_b2
+start_a3
+start_a4
+main
+finish_a4
+finish_a3
+finish_b2
+finish_b1
+finish_a2
+finish_a1
diff --git a/REORG.TODO/elf/tst-initorder2.c b/REORG.TODO/elf/tst-initorder2.c
new file mode 100644
index 0000000000..050f9568b8
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorder2.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+#ifndef NAME
+int
+main (void)
+{
+  puts ("main");
+}
+#else
+static void __attribute__ ((constructor))
+init (void)
+{
+  puts ("init: " NAME);
+}
+static void __attribute__ ((destructor))
+fini (void)
+{
+  puts ("fini: " NAME);
+}
+#endif
diff --git a/REORG.TODO/elf/tst-initorder2.exp b/REORG.TODO/elf/tst-initorder2.exp
new file mode 100644
index 0000000000..5169489b85
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorder2.exp
@@ -0,0 +1,9 @@
+init: d
+init: c
+init: b
+init: a
+main
+fini: a
+fini: b
+fini: c
+fini: d
diff --git a/REORG.TODO/elf/tst-initordera1.c b/REORG.TODO/elf/tst-initordera1.c
new file mode 100644
index 0000000000..f161257142
--- /dev/null
+++ b/REORG.TODO/elf/tst-initordera1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a1( void ) __attribute__((constructor));
+extern void finish_a1( void ) __attribute__((destructor));
+
+void
+start_a1( void )
+{
+  printf( "start_a1\n" );
+}
+
+void
+finish_a1( void )
+{
+  printf( "finish_a1\n" );
+}
diff --git a/REORG.TODO/elf/tst-initordera2.c b/REORG.TODO/elf/tst-initordera2.c
new file mode 100644
index 0000000000..a5a9b42ff6
--- /dev/null
+++ b/REORG.TODO/elf/tst-initordera2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a2( void ) __attribute__((constructor));
+extern void finish_a2( void ) __attribute__((destructor));
+
+void
+start_a2( void )
+{
+  printf( "start_a2\n" );
+}
+
+void
+finish_a2( void )
+{
+  printf( "finish_a2\n" );
+}
diff --git a/REORG.TODO/elf/tst-initordera3.c b/REORG.TODO/elf/tst-initordera3.c
new file mode 100644
index 0000000000..1c7f496e9a
--- /dev/null
+++ b/REORG.TODO/elf/tst-initordera3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a3( void ) __attribute__((constructor));
+extern void finish_a3( void ) __attribute__((destructor));
+
+void
+start_a3( void )
+{
+  printf( "start_a3\n" );
+}
+
+void
+finish_a3( void )
+{
+  printf( "finish_a3\n" );
+}
diff --git a/REORG.TODO/elf/tst-initordera4.c b/REORG.TODO/elf/tst-initordera4.c
new file mode 100644
index 0000000000..70b9f5e392
--- /dev/null
+++ b/REORG.TODO/elf/tst-initordera4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a4( void ) __attribute__((constructor));
+extern void finish_a4( void ) __attribute__((destructor));
+
+void
+start_a4( void )
+{
+  printf( "start_a4\n" );
+}
+
+void
+finish_a4( void )
+{
+  printf( "finish_a4\n" );
+}
diff --git a/REORG.TODO/elf/tst-initorderb1.c b/REORG.TODO/elf/tst-initorderb1.c
new file mode 100644
index 0000000000..993ea3fe30
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorderb1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_b1( void ) __attribute__((constructor));
+extern void finish_b1( void ) __attribute__((destructor));
+
+void
+start_b1( void )
+{
+  printf( "start_b1\n" );
+}
+
+void
+finish_b1( void )
+{
+  printf( "finish_b1\n" );
+}
diff --git a/REORG.TODO/elf/tst-initorderb2.c b/REORG.TODO/elf/tst-initorderb2.c
new file mode 100644
index 0000000000..3334dda0a9
--- /dev/null
+++ b/REORG.TODO/elf/tst-initorderb2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_b2( void ) __attribute__((constructor));
+extern void finish_b2( void ) __attribute__((destructor));
+
+void
+start_b2( void )
+{
+  printf( "start_b2\n" );
+}
+
+void
+finish_b2( void )
+{
+  printf( "finish_b2\n" );
+}
diff --git a/REORG.TODO/elf/tst-latepthread.c b/REORG.TODO/elf/tst-latepthread.c
new file mode 100644
index 0000000000..ca2f82243d
--- /dev/null
+++ b/REORG.TODO/elf/tst-latepthread.c
@@ -0,0 +1,104 @@
+/* Test that loading libpthread does not break ld.so exceptions (bug 16628).
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+  void *handle = dlopen ("tst-latepthreadmod.so", RTLD_LOCAL | RTLD_LAZY);
+  if (handle == NULL)
+    {
+      printf ("error: dlopen failed: %s\n", dlerror ());
+      return 1;
+    }
+  void *ptr = dlsym (handle, "trigger_dynlink_failure");
+  if (ptr == NULL)
+    {
+      printf ("error: dlsym failed: %s\n", dlerror ());
+      return 1;
+    }
+  int (*func) (void) = ptr;
+
+  /* Run the actual test in a subprocess, to capture the error.  */
+  int fds[2];
+  if (pipe (fds) < 0)
+    {
+      printf ("error: pipe: %m\n");
+      return 1;
+    }
+  pid_t pid = fork ();
+  if (pid < 0)
+    {
+      printf ("error: fork: %m\n");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      if (dup2 (fds[1], STDERR_FILENO) < 0)
+        _exit (2);
+      /* Trigger an abort.  */
+      func ();
+      _exit (3);
+    }
+  /* NB: This assumes that the abort message is so short that the pipe
+     does not block.  */
+  int status;
+  if (waitpid (pid, &status, 0) < 0)
+    {
+      printf ("error: waitpid: %m\n");
+      return 1;
+    }
+
+  /* Check the printed error message.  */
+  if (close (fds[1]) < 0)
+   {
+     printf ("error: close: %m\n");
+     return 1;
+   }
+  char buf[512];
+  /* Leave room for the NUL terminator.  */
+  ssize_t ret = read (fds[0], buf, sizeof (buf) - 1);
+  if (ret < 0)
+    {
+      printf ("error: read: %m\n");
+      return 1;
+    }
+  if (ret > 0 && buf[ret - 1] == '\n')
+    --ret;
+  buf[ret] = '\0';
+  printf ("info: exit status: %d, message: %s\n", status, buf);
+  if (strstr (buf, "undefined symbol: this_function_is_not_defined") == NULL)
+    {
+      printf ("error: message does not contain expected string\n");
+      return 1;
+    }
+  if (!WIFEXITED (status) || WEXITSTATUS (status) != 127)
+    {
+      printf ("error: unexpected process exit status\n");
+      return 1;
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-latepthreadmod.c b/REORG.TODO/elf/tst-latepthreadmod.c
new file mode 100644
index 0000000000..35a82d388b
--- /dev/null
+++ b/REORG.TODO/elf/tst-latepthreadmod.c
@@ -0,0 +1,33 @@
+/* DSO which links against libpthread and triggers a lazy binding.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled into a DSO which loads libpthread, but fails
+   the dynamic linker afterwards.  */
+
+#include <pthread.h>
+
+/* Link in libpthread.  */
+void *pthread_create_ptr = &pthread_create;
+
+int this_function_is_not_defined (void);
+
+int
+trigger_dynlink_failure (void)
+{
+  return this_function_is_not_defined ();
+}
diff --git a/REORG.TODO/elf/tst-ldconfig-X.sh b/REORG.TODO/elf/tst-ldconfig-X.sh
new file mode 100644
index 0000000000..e97ca89946
--- /dev/null
+++ b/REORG.TODO/elf/tst-ldconfig-X.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Test that ldconfig -X does not remove stale symbolic links.
+# Copyright (C) 2000-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+set -ex
+
+common_objpfx=$1
+test_wrapper_env=$2
+run_program_env=$3
+
+testroot="${common_objpfx}elf/bug19610-test-directory"
+cleanup () {
+    rm -rf "$testroot"
+}
+trap cleanup 0
+
+rm -rf "$testroot"
+mkdir -p $testroot/lib $testroot/etc
+
+# Relative symbolic link target.
+ln -s libdoesnotexist.so.1.1 $testroot/lib/libdoesnotexist.so.1
+
+# Absolute symbolic link target.
+ln -s $testroot/opt/sw/lib/libdoesnotexist2.so.1.1 $testroot/lib/
+
+errors=0
+check_files () {
+    for name in libdoesnotexist.so.1 libdoesnotexist2.so.1.1 ; do
+	path="$testroot/lib/$name"
+	if test ! -h $path ; then
+	    echo "error: missing file: $path"
+	    errors=1
+	fi
+    done
+}
+
+check_files
+
+${test_wrapper_env} \
+${run_program_env} \
+${common_objpfx}elf/ldconfig -X -f /dev/null \
+  -C $testroot/etc/ld.so.cache \
+  $testroot/lib
+
+check_files
+
+exit $errors
diff --git a/REORG.TODO/elf/tst-leaks1-static.c b/REORG.TODO/elf/tst-leaks1-static.c
new file mode 100644
index 0000000000..b956d66905
--- /dev/null
+++ b/REORG.TODO/elf/tst-leaks1-static.c
@@ -0,0 +1 @@
+#include "tst-leaks1.c"
diff --git a/REORG.TODO/elf/tst-leaks1.c b/REORG.TODO/elf/tst-leaks1.c
new file mode 100644
index 0000000000..d67e8269c4
--- /dev/null
+++ b/REORG.TODO/elf/tst-leaks1.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  mtrace ();
+
+  int ret = 0;
+  for (int i = 0; i < 10; i++)
+    {
+      void *h = dlopen (i < 5 ? "./tst-leaks1.c"
+			      : "$ORIGIN/tst-leaks1.o", RTLD_LAZY);
+      if (h != NULL)
+	{
+	  puts ("dlopen unexpectedly succeeded");
+	  ret = 1;
+	  dlclose (h);
+	}
+    }
+
+  return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-linkall-static.c b/REORG.TODO/elf/tst-linkall-static.c
new file mode 100644
index 0000000000..8f40657244
--- /dev/null
+++ b/REORG.TODO/elf/tst-linkall-static.c
@@ -0,0 +1,52 @@
+/* Test static linking against multiple libraries, to find symbol conflicts.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <pthread.h>
+#include <crypt.h>
+#include <resolv.h>
+#include <dlfcn.h>
+#include <utmp.h>
+#include <aio.h>
+#include <netdb.h>
+
+/* These references force linking the executable against central
+   functions in the static libraries, pulling significant parts of
+   each library into the link.  */
+void *references[] =
+  {
+    &pow,                       /* libm */
+    &pthread_create,            /* libpthread */
+#if USE_CRYPT
+    &crypt,                     /* libcrypt */
+#endif
+    &res_send,                  /* libresolv */
+    &dlopen,                    /* libdl */
+    &login,                     /* libutil */
+    &aio_init,                  /* librt */
+    &getaddrinfo_a,             /* libanl */
+  };
+
+static int
+do_test (void)
+{
+  /* This is a link-time test.  There is nothing to run here.  */
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-nodelete-dlclose-dso.c b/REORG.TODO/elf/tst-nodelete-dlclose-dso.c
new file mode 100644
index 0000000000..4042c78b8a
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-dlclose-dso.c
@@ -0,0 +1,90 @@
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is the primary DSO that is loaded by the appliation.  This DSO
+   then loads a plugin with RTLD_NODELETE.  This plugin depends on this
+   DSO.  This dependency chain means that at application shutdown the
+   plugin will be destructed first.  Thus by the time this DSO is
+   destructed we will be calling dlclose on an object that has already
+   been destructed.  It is allowed to call dlclose in this way and
+   should not assert.  */
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+/* Plugin to load.  */
+static void *plugin_lib = NULL;
+/* Plugin function.  */
+static void (*plugin_func) (void);
+#define LIB_PLUGIN "tst-nodelete-dlclose-plugin.so"
+
+/* This function is never called but the plugin references it.
+   We do this to avoid any future --as-needed from removing the
+   plugin's DT_NEEDED on this DSO (required for the test).  */
+void
+primary_reference (void)
+{
+  printf ("INFO: Called primary_reference function.\n");
+}
+
+void
+primary (void)
+{
+  char *error;
+
+  plugin_lib = dlopen (LIB_PLUGIN, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
+  if (plugin_lib == NULL)
+    {
+      printf ("ERROR: Unable to load plugin library.\n");
+      exit (EXIT_FAILURE);
+    }
+  dlerror ();
+
+  plugin_func = (void (*) (void)) dlsym (plugin_lib, "plugin_func");
+  error = dlerror ();
+  if (error != NULL)
+    {
+      printf ("ERROR: Unable to find symbol with error \"%s\".",
+	      error);
+      exit (EXIT_FAILURE);
+    }
+
+  return;
+}
+
+__attribute__ ((destructor))
+static void
+primary_dtor (void)
+{
+  int ret;
+
+  printf ("INFO: Calling primary destructor.\n");
+
+  /* The destructor runs in the test driver also, which
+     hasn't called primary, in that case do nothing.  */
+  if (plugin_lib == NULL)
+    return;
+
+  ret = dlclose (plugin_lib);
+  if (ret != 0)
+    {
+      printf ("ERROR: Calling dlclose failed with \"%s\"\n",
+	      dlerror ());
+      exit (EXIT_FAILURE);
+    }
+}
diff --git a/REORG.TODO/elf/tst-nodelete-dlclose-plugin.c b/REORG.TODO/elf/tst-nodelete-dlclose-plugin.c
new file mode 100644
index 0000000000..00c84d0bc0
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-dlclose-plugin.c
@@ -0,0 +1,40 @@
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This DSO simulates a plugin with a dependency on the
+   primary DSO loaded by the appliation.  */
+#include <stdio.h>
+
+extern void primary_reference (void);
+
+void
+plugin_func (void)
+{
+  printf ("INFO: Calling plugin function.\n");
+  /* Need a reference to the DSO to ensure that a potential --as-needed
+     doesn't remove the DT_NEEDED entry which we rely upon to ensure
+     destruction ordering.  */
+  primary_reference ();
+}
+
+__attribute__ ((destructor))
+static void
+plugin_dtor (void)
+{
+  printf ("INFO: Calling plugin destructor.\n");
+}
diff --git a/REORG.TODO/elf/tst-nodelete-dlclose.c b/REORG.TODO/elf/tst-nodelete-dlclose.c
new file mode 100644
index 0000000000..178673e9d0
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-dlclose.c
@@ -0,0 +1,35 @@
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This simulates an application using the primary DSO which loads the
+   plugin DSO.  */
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void primary (void);
+
+static int
+do_test (void)
+{
+  printf ("INFO: Starting application.\n");
+  primary ();
+  printf ("INFO: Exiting application.\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-nodelete-opened-lib.c b/REORG.TODO/elf/tst-nodelete-opened-lib.c
new file mode 100644
index 0000000000..3e1dcdfc1b
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-opened-lib.c
@@ -0,0 +1,19 @@
+/* Verify that objects opened with RTLD_NODELETE are not unloaded - the DSO.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int foo_var = 42;
diff --git a/REORG.TODO/elf/tst-nodelete-opened.c b/REORG.TODO/elf/tst-nodelete-opened.c
new file mode 100644
index 0000000000..d71efa4603
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-opened.c
@@ -0,0 +1,68 @@
+/* Verify that an already opened DSO opened agained with RTLD_NODELETE actually
+   sets the NODELETE flag.
+
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+do_test (void)
+{
+  void *h1 = dlopen ("$ORIGIN/tst-nodelete-opened-lib.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      printf ("h1: failed to open DSO: %s\n", dlerror ());
+      return 1;
+    }
+
+  void *h2 = dlopen ("$ORIGIN/tst-nodelete-opened-lib.so",
+		     RTLD_LAZY | RTLD_NODELETE);
+  if (h2 == NULL)
+    {
+      printf ("h2: failed to open DSO: %s\n", dlerror ());
+      return 1;
+    }
+
+  int *foo = dlsym (h2, "foo_var");
+  if (foo == NULL)
+    {
+      printf ("failed to load symbol foo_var: %s\n", dlerror ());
+      return 1;
+    }
+
+  if (dlclose (h1) != 0)
+    {
+      printf ("h1: dlclose failed: %s\n", dlerror ());
+      return 1;
+    }
+
+  if (dlclose (h2) != 0)
+    {
+      printf ("h2: dlclose failed: %s\n", dlerror ());
+      return 1;
+    }
+
+  /* This FOO dereference will crash with a segfault if the DSO was
+     unloaded.  */
+  printf ("foo == %d\n", *foo);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-nodelete-rtldmod.cc b/REORG.TODO/elf/tst-nodelete-rtldmod.cc
new file mode 100644
index 0000000000..740e1d8181
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-rtldmod.cc
@@ -0,0 +1,6 @@
+extern int not_exist (void);
+
+int foo (void)
+{
+  return not_exist ();
+}
diff --git a/REORG.TODO/elf/tst-nodelete-uniquemod.cc b/REORG.TODO/elf/tst-nodelete-uniquemod.cc
new file mode 100644
index 0000000000..632b303d58
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-uniquemod.cc
@@ -0,0 +1,14 @@
+extern int not_exist (void);
+
+inline int make_unique (void)
+{
+  /* Static variables in inline functions and classes
+     generate STB_GNU_UNIQUE symbols.  */
+  static int unique;
+  return ++unique;
+}
+
+int foo (void)
+{
+  return make_unique () + not_exist ();
+}
diff --git a/REORG.TODO/elf/tst-nodelete-zmod.cc b/REORG.TODO/elf/tst-nodelete-zmod.cc
new file mode 100644
index 0000000000..740e1d8181
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete-zmod.cc
@@ -0,0 +1,6 @@
+extern int not_exist (void);
+
+int foo (void)
+{
+  return not_exist ();
+}
diff --git a/REORG.TODO/elf/tst-nodelete.cc b/REORG.TODO/elf/tst-nodelete.cc
new file mode 100644
index 0000000000..5752e7df26
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete.cc
@@ -0,0 +1,50 @@
+#include "../dlfcn/dlfcn.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  /* This is a test for correct handling of dlopen failures for library that
+     is loaded with RTLD_NODELETE flag.  The first dlopen should fail because
+     of undefined symbols in shared library.  The second dlopen then verifies
+     that library was properly unloaded.  */
+  if (dlopen ("tst-nodelete-rtldmod.so", RTLD_NOW | RTLD_NODELETE) != NULL
+      || dlopen ("tst-nodelete-rtldmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+    {
+      printf ("RTLD_NODELETE test failed\n");
+      result = 1;
+    }
+
+  /* This is a test for correct handling of dlopen failures for library that
+     is linked with '-z nodelete' option and hence has DF_1_NODELETE flag.
+     The first dlopen should fail because of undefined symbols in shared
+     library.  The second dlopen then verifies that library was properly
+     unloaded.  */
+  if (dlopen ("tst-nodelete-zmod.so", RTLD_NOW) != NULL
+      || dlopen ("tst-nodelete-zmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+    {
+      printf ("-z nodelete test failed\n");
+      result = 1;
+    }
+
+   /* This is a test for correct handling of dlopen failures for library
+     with unique symbols.  The first dlopen should fail because of undefined
+     symbols in shared library.  The second dlopen then verifies that library
+     was properly unloaded.  */
+  if (dlopen ("tst-nodelete-uniquemod.so", RTLD_NOW) != NULL
+      || dlopen ("tst-nodelete-uniquemod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+    {
+      printf ("Unique symbols test failed\n");
+      result = 1;
+    }
+
+  if (result == 0)
+    printf ("SUCCESS\n");
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-nodelete2.c b/REORG.TODO/elf/tst-nodelete2.c
new file mode 100644
index 0000000000..010c4ae237
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete2.c
@@ -0,0 +1,36 @@
+#include "../dlfcn/dlfcn.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnu/lib-names.h>
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  printf ("\nOpening pthread library.\n");
+  void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
+
+  /* This is a test for correct DF_1_NODELETE clearing when dlopen failure
+     happens.  We should clear DF_1_NODELETE for failed library only, because
+     doing this for others (e.g. libpthread) might cause them to be unloaded,
+     that may lead to some global references (e.g. __rtld_lock_unlock) to be
+     broken.  The dlopen should fail because of undefined symbols in shared
+     library, that cause DF_1_NODELETE to be cleared.  For libpthread, this
+     flag should be set, because if not, SIGSEGV will happen in dlclose.  */
+  if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL)
+    {
+      printf ("Unique symbols test failed\n");
+      result = 1;
+    }
+
+  if (pthread)
+    dlclose (pthread);
+
+  if (result == 0)
+    printf ("SUCCESS\n");
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-nodelete2mod.c b/REORG.TODO/elf/tst-nodelete2mod.c
new file mode 100644
index 0000000000..e88c756f5e
--- /dev/null
+++ b/REORG.TODO/elf/tst-nodelete2mod.c
@@ -0,0 +1,7 @@
+/* Undefined symbol.  */
+extern int not_exist (void);
+
+int foo (void)
+{
+  return not_exist ();
+}
diff --git a/REORG.TODO/elf/tst-noload.c b/REORG.TODO/elf/tst-noload.c
new file mode 100644
index 0000000000..3fb2895e2c
--- /dev/null
+++ b/REORG.TODO/elf/tst-noload.c
@@ -0,0 +1,72 @@
+/* Verify that RTLD_NOLOAD works as expected.
+
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <gnu/lib-names.h>
+
+static int
+do_test (void)
+{
+  /* Test that no object is loaded with RTLD_NOLOAD.  */
+  void *h1 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD);
+  if (h1 != NULL)
+    {
+      printf ("h1: DSO has been loaded while it should have not\n");
+      return 1;
+    }
+
+  /* This used to segfault in some glibc versions.  */
+  void *h2 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD | RTLD_NODELETE);
+  if (h2 != NULL)
+    {
+      printf ("h2: DSO has been loaded while it should have not\n");
+      return 1;
+    }
+
+  /* Test that loading an already loaded object returns the same.  */
+  void *h3 = dlopen (LIBM_SO, RTLD_LAZY);
+  if (h3 == NULL)
+    {
+      printf ("h3: failed to open DSO: %s\n", dlerror ());
+      return 1;
+    }
+  void *h4 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD);
+  if (h4 == NULL)
+    {
+      printf ("h4: failed to open DSO: %s\n", dlerror ());
+      return 1;
+    }
+  if (h4 != h3)
+    {
+      printf ("h4: should return the same object\n");
+      return 1;
+    }
+
+  /* Cleanup */
+  if (dlclose (h3) != 0)
+    {
+      printf ("h3: dlclose failed: %s\n", dlerror ());
+      return 1;
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-null-argv-lib.c b/REORG.TODO/elf/tst-null-argv-lib.c
new file mode 100644
index 0000000000..12af03ba95
--- /dev/null
+++ b/REORG.TODO/elf/tst-null-argv-lib.c
@@ -0,0 +1,24 @@
+/* Verify that program does not crash when LD_DEBUG is set and the program name
+   is not available.  This is the library.
+   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+void
+foo (void)
+{
+  return;
+}
diff --git a/REORG.TODO/elf/tst-null-argv.c b/REORG.TODO/elf/tst-null-argv.c
new file mode 100644
index 0000000000..21b87327c1
--- /dev/null
+++ b/REORG.TODO/elf/tst-null-argv.c
@@ -0,0 +1,36 @@
+/* Verify that program does not crash when LD_DEBUG is set and the program name
+   is not available.
+   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+extern void foo (void);
+
+int
+do_test (int argc, char **argv)
+{
+  argv[0] = argv[1];
+  argc--;
+
+  /* This should result in a symbol lookup, causing a volley of debug output
+     when LD_DEBUG=symbols.  */
+  foo ();
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-order-a1.c b/REORG.TODO/elf/tst-order-a1.c
new file mode 100644
index 0000000000..f161257142
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-a1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a1( void ) __attribute__((constructor));
+extern void finish_a1( void ) __attribute__((destructor));
+
+void
+start_a1( void )
+{
+  printf( "start_a1\n" );
+}
+
+void
+finish_a1( void )
+{
+  printf( "finish_a1\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-a2.c b/REORG.TODO/elf/tst-order-a2.c
new file mode 100644
index 0000000000..a5a9b42ff6
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-a2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a2( void ) __attribute__((constructor));
+extern void finish_a2( void ) __attribute__((destructor));
+
+void
+start_a2( void )
+{
+  printf( "start_a2\n" );
+}
+
+void
+finish_a2( void )
+{
+  printf( "finish_a2\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-a3.c b/REORG.TODO/elf/tst-order-a3.c
new file mode 100644
index 0000000000..1c7f496e9a
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-a3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a3( void ) __attribute__((constructor));
+extern void finish_a3( void ) __attribute__((destructor));
+
+void
+start_a3( void )
+{
+  printf( "start_a3\n" );
+}
+
+void
+finish_a3( void )
+{
+  printf( "finish_a3\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-a4.c b/REORG.TODO/elf/tst-order-a4.c
new file mode 100644
index 0000000000..70b9f5e392
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-a4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_a4( void ) __attribute__((constructor));
+extern void finish_a4( void ) __attribute__((destructor));
+
+void
+start_a4( void )
+{
+  printf( "start_a4\n" );
+}
+
+void
+finish_a4( void )
+{
+  printf( "finish_a4\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-b1.c b/REORG.TODO/elf/tst-order-b1.c
new file mode 100644
index 0000000000..993ea3fe30
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-b1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_b1( void ) __attribute__((constructor));
+extern void finish_b1( void ) __attribute__((destructor));
+
+void
+start_b1( void )
+{
+  printf( "start_b1\n" );
+}
+
+void
+finish_b1( void )
+{
+  printf( "finish_b1\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-b2.c b/REORG.TODO/elf/tst-order-b2.c
new file mode 100644
index 0000000000..3334dda0a9
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-b2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern void start_b2( void ) __attribute__((constructor));
+extern void finish_b2( void ) __attribute__((destructor));
+
+void
+start_b2( void )
+{
+  printf( "start_b2\n" );
+}
+
+void
+finish_b2( void )
+{
+  printf( "finish_b2\n" );
+}
diff --git a/REORG.TODO/elf/tst-order-main.c b/REORG.TODO/elf/tst-order-main.c
new file mode 100644
index 0000000000..2a90130db6
--- /dev/null
+++ b/REORG.TODO/elf/tst-order-main.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  printf( "main\n" );
+  exit(EXIT_SUCCESS);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-pathopt.c b/REORG.TODO/elf/tst-pathopt.c
new file mode 100644
index 0000000000..e2c96fbc72
--- /dev/null
+++ b/REORG.TODO/elf/tst-pathopt.c
@@ -0,0 +1,41 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int
+do_test (void)
+{
+  void *h;
+  int (*fp) (int);
+  int result;
+
+  mtrace ();
+
+  h = dlopen ("renamed.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("failed to load \"%s\": %s\n", "renamed.so", dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "in_renamed");
+  if (fp == NULL)
+    {
+      printf ("lookup of \"%s\" failed: %s\n", "in_renamed", dlerror ());
+      exit (1);
+    }
+
+  result = fp (10);
+
+  if (dlclose (h) != 0)
+    {
+      printf ("failed to close \"%s\": %s\n", "renamed.so", dlerror ());
+      exit (1);
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-pathopt.sh b/REORG.TODO/elf/tst-pathopt.sh
new file mode 100755
index 0000000000..4183a697dc
--- /dev/null
+++ b/REORG.TODO/elf/tst-pathopt.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Test lookup path optimization.
+# Copyright (C) 2000-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_wrapper_env=$2
+run_program_env=$3
+
+test -e ${common_objpfx}elf/will-be-empty &&
+  rm -fr ${common_objpfx}elf/will-be-empty
+test -d ${common_objpfx}elf/for-renamed ||
+  mkdir ${common_objpfx}elf/for-renamed
+
+cp ${common_objpfx}elf/pathoptobj.so ${common_objpfx}elf/for-renamed/renamed.so
+
+${test_wrapper_env} \
+${run_program_env} \
+LD_LIBRARY_PATH=${common_objpfx}elf/will-be-empty:${common_objpfx}elf/for-renamed:${common_objpfx}.:${common_objpfx}dlfcn \
+  ${common_objpfx}elf/ld.so ${common_objpfx}elf/tst-pathopt \
+    > ${common_objpfx}elf/tst-pathopt.out
+
+exit $?
diff --git a/REORG.TODO/elf/tst-pie1.c b/REORG.TODO/elf/tst-pie1.c
new file mode 100644
index 0000000000..75d941f21f
--- /dev/null
+++ b/REORG.TODO/elf/tst-pie1.c
@@ -0,0 +1,5 @@
+int
+foo (void)
+{
+  return 34;
+}
diff --git a/REORG.TODO/elf/tst-pie2.c b/REORG.TODO/elf/tst-pie2.c
new file mode 100644
index 0000000000..32943bbc1a
--- /dev/null
+++ b/REORG.TODO/elf/tst-pie2.c
@@ -0,0 +1,40 @@
+/* Test case for BZ #16381
+
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+#include <assert.h>
+
+static int g;
+
+void init_g (void) __attribute__((constructor));
+
+void
+init_g (void)
+{
+  assert (g == 0);
+  g += 1;
+}
+
+static int
+do_test (void)
+{
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-piemod1.c b/REORG.TODO/elf/tst-piemod1.c
new file mode 100644
index 0000000000..72d7e0a187
--- /dev/null
+++ b/REORG.TODO/elf/tst-piemod1.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int
+foo (void)
+{
+  return 21;
+}
+
+static int
+do_test (void)
+{
+  int val = foo ();
+  if (val != 34)
+    {
+      printf ("foo () returned %d\n", val);
+      return 1;
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-prelink.c b/REORG.TODO/elf/tst-prelink.c
new file mode 100644
index 0000000000..7435c321d3
--- /dev/null
+++ b/REORG.TODO/elf/tst-prelink.c
@@ -0,0 +1,29 @@
+/* Test the output from the environment variable, LD_TRACE_PRELINKING,
+   for prelink.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  fprintf (stdout, "hello\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-prelink.exp b/REORG.TODO/elf/tst-prelink.exp
new file mode 100644
index 0000000000..b35b4c9705
--- /dev/null
+++ b/REORG.TODO/elf/tst-prelink.exp
@@ -0,0 +1 @@
+/0 stdout
diff --git a/REORG.TODO/elf/tst-protected1a.c b/REORG.TODO/elf/tst-protected1a.c
new file mode 100644
index 0000000000..4267b951c4
--- /dev/null
+++ b/REORG.TODO/elf/tst-protected1a.c
@@ -0,0 +1,234 @@
+/* Test the protected visibility when main is linked with moda and modb
+   in that order:
+   1. Protected symbols, protected1, protected2 and protected3, defined
+      in moda, are used in moda.
+   2. Protected symbol, protected3, defined in modb, are used in modb.
+   3. Symbol, protected1, defined in moda, is also used in main and modb.
+   4. Symbol, protected2, defined in main, is used in main.
+   5. Symbol, protected3, defined in moda, is also used in main.
+
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file must be compiled as PIE to avoid copy relocation when
+   accessing protected symbols defined in shared libaries since copy
+   relocation doesn't work with protected symbols and linker in
+   binutils 2.26 enforces this rule.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected1mod.h"
+
+/* Prototype for our test function.  */
+extern int do_test (void);
+
+int protected2 = -1;
+
+/* This defines the `main' function and some more.  */
+#include <support/test-driver.c>
+
+int
+do_test (void)
+{
+  int res = 0;
+
+  /* Check if we get the same address for the protected data symbol.  */
+  if (&protected1 != protected1a_p ())
+    {
+      puts ("`protected1' in main and moda doesn't have same address");
+      res = 1;
+    }
+  if (&protected1 != protected1b_p ())
+    {
+      puts ("`protected1' in main and modb doesn't have same address");
+      res = 1;
+    }
+
+  /* Check if we get the right value for the protected data symbol.  */
+  if (protected1 != 3)
+    {
+      puts ("`protected1' in main and moda doesn't have same value");
+      res = 1;
+    }
+
+  /* Check if we get the right value for data defined in executable.  */
+  if (protected2 != -1)
+    {
+      puts ("`protected2' in main has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the same address for the protected data symbol.  */
+  if (&protected3 != protected3a_p ())
+    {
+      puts ("`protected3' in main and moda doesn't have same address");
+      res = 1;
+    }
+  if (&protected3 == protected3b_p ())
+    {
+      puts ("`protected3' in main and modb has same address");
+      res = 1;
+    }
+
+  /* Check if we get the right value for the protected data symbol.  */
+  if (protected3 != 5)
+    {
+      puts ("`protected3' in main and moda doesn't have same value");
+      res = 1;
+    }
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected2' in moda to 30.  */
+  set_protected2 (300);
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected1' in moda to 30.  */
+  set_protected1a (30);
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected1 != 30)
+    {
+      puts ("`protected1' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  protected2 = -300;
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if data defined in executable is changed.  */
+  if (protected2 != -300)
+    {
+      puts ("`protected2' in main is changed");
+      res = 1;
+    }
+
+  /* Set `protected1' in modb to 40.  */
+  set_protected1b (40);
+  set_expected_protected1 (40);
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected1 != 40)
+    {
+      puts ("`protected1' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Set `protected3' in moda to 80.  */
+  set_protected3a (80);
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected3 != 80)
+    {
+      puts ("`protected3' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected3' in modb to 100.  */
+  set_protected3b (100);
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected3 != 80)
+    {
+      puts ("`protected3' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  return res;
+}
diff --git a/REORG.TODO/elf/tst-protected1b.c b/REORG.TODO/elf/tst-protected1b.c
new file mode 100644
index 0000000000..9fd695bffa
--- /dev/null
+++ b/REORG.TODO/elf/tst-protected1b.c
@@ -0,0 +1,240 @@
+/* Test the protected visibility when main is linked with modb and moda
+   in that order:
+   1. Protected symbols, protected1, protected2 and protected3, defined
+      in moda, are used in moda.
+   2.  Protected symbol, protected3, defined in modb, are used in modb
+   3. Symbol, protected1, defined in modb, is used in main and modb.
+   4. Symbol, protected2, defined in main, is used in main.
+   5. Symbol, protected3, defined in modb, is also used in main.
+
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file must be compiled as PIE to avoid copy relocation when
+   accessing protected symbols defined in shared libaries since copy
+   relocation doesn't work with protected symbols and linker in
+   binutils 2.26 enforces this rule.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected1mod.h"
+
+/* Prototype for our test function.  */
+extern int do_test (void);
+
+int protected2 = -1;
+
+/* This defines the `main' function and some more.  */
+#include <support/test-driver.c>
+
+int
+do_test (void)
+{
+  int res = 0;
+
+  /* Check if we get the same address for the protected data symbol.  */
+  if (&protected1 == protected1a_p ())
+    {
+      puts ("`protected1' in main and moda has  same address");
+      res = 1;
+    }
+  if (&protected1 != protected1b_p ())
+    {
+      puts ("`protected1' in main and modb doesn't have same address");
+      res = 1;
+    }
+
+  /* Check if we get the right value for the protected data symbol.  */
+  if (protected1 != -3)
+    {
+      puts ("`protected1' in main and modb doesn't have same value");
+      res = 1;
+    }
+
+  /* Check if we get the right value for data defined in executable.  */
+  if (protected2 != -1)
+    {
+      puts ("`protected2' in main has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the same address for the protected data symbol.  */
+  if (&protected3 == protected3a_p ())
+    {
+      puts ("`protected3' in main and moda has same address");
+      res = 1;
+    }
+  if (&protected3 != protected3b_p ())
+    {
+      puts ("`protected3' in main and modb doesn't have same address");
+      res = 1;
+    }
+
+  /* Check if we get the right value for the protected data symbol.  */
+  if (protected3 != -5)
+    {
+      puts ("`protected3' in main and modb doesn't have same value");
+      res = 1;
+    }
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected2' in moda to 30.  */
+  set_protected2 (300);
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the right value for data defined in executable.  */
+  if (protected2 != -1)
+    {
+      puts ("`protected2' in main has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected1' in moda to 30.  */
+  set_protected1a (30);
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the same value for the protected data symbol.  */
+  if (protected1 != -3)
+    {
+      puts ("`protected1' in main has the wrong value");
+      res = 1;
+    }
+
+  protected2 = -300;
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if data defined in executable is changed.  */
+  if (protected2 != -300)
+    {
+      puts ("`protected2' in main is changed");
+      res = 1;
+    }
+
+  /* Set `protected1' in modb to 40.  */
+  set_protected1b (40);
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected1 != 40)
+    {
+      puts ("`protected1' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Set `protected3' in moda to 80.  */
+  set_protected3a (80);
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected3 != -5)
+    {
+      puts ("`protected3' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  /* Set `protected3' in modb to 100.  */
+  set_protected3b (100);
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the updated value for the protected data symbol.  */
+  if (protected3 != 100)
+    {
+      puts ("`protected3' in main doesn't have the updated value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  return res;
+}
diff --git a/REORG.TODO/elf/tst-protected1mod.h b/REORG.TODO/elf/tst-protected1mod.h
new file mode 100644
index 0000000000..a47d65f6b1
--- /dev/null
+++ b/REORG.TODO/elf/tst-protected1mod.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Prototypes for the functions in the DSOs.  */
+extern int protected1;
+extern int protected2;
+extern int protected3;
+
+extern void set_protected1a (int);
+extern void set_protected1b (int);
+extern int *protected1a_p (void);
+extern int *protected1b_p (void);
+
+extern void set_expected_protected1 (int);
+extern int check_protected1 (void);
+
+extern void set_protected2 (int);
+extern int check_protected2 (void);
+
+extern void set_expected_protected3a (int);
+extern void set_protected3a (int);
+extern int check_protected3a (void);
+extern int *protected3a_p (void);
+extern void set_expected_protected3b (int);
+extern void set_protected3b (int);
+extern int check_protected3b (void);
+extern int *protected3b_p (void);
diff --git a/REORG.TODO/elf/tst-protected1moda.c b/REORG.TODO/elf/tst-protected1moda.c
new file mode 100644
index 0000000000..aca4fc82a8
--- /dev/null
+++ b/REORG.TODO/elf/tst-protected1moda.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tst-protected1mod.h"
+
+int protected1 = 3;
+static int expected_protected1 = 3;
+int protected2 = 4;
+static int expected_protected2 = 4;
+int protected3 = 5;
+static int expected_protected3 = 5;
+
+asm (".protected protected1");
+asm (".protected protected2");
+asm (".protected protected3");
+
+void
+set_protected1a (int i)
+{
+  protected1 = i;
+  set_expected_protected1 (i);
+}
+
+void
+set_expected_protected1 (int i)
+{
+  expected_protected1 = i;
+}
+
+int *
+protected1a_p (void)
+{
+  return &protected1;
+}
+
+int
+check_protected1 (void)
+{
+  return protected1 == expected_protected1;
+}
+
+void
+set_protected2 (int i)
+{
+  protected2 = i;
+  expected_protected2 = i;
+}
+
+int
+check_protected2 (void)
+{
+  return protected2 == expected_protected2;
+}
+
+void
+set_expected_protected3a (int i)
+{
+  expected_protected3 = i;
+}
+
+void
+set_protected3a (int i)
+{
+  protected3 = i;
+  set_expected_protected3a (i);
+}
+
+int
+check_protected3a (void)
+{
+  return protected3 == expected_protected3;
+}
+
+int *
+protected3a_p (void)
+{
+  return &protected3;
+}
diff --git a/REORG.TODO/elf/tst-protected1modb.c b/REORG.TODO/elf/tst-protected1modb.c
new file mode 100644
index 0000000000..5036b6c3e7
--- /dev/null
+++ b/REORG.TODO/elf/tst-protected1modb.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include "tst-protected1mod.h"
+
+int protected1 = -3;
+int protected3 = -5;
+static int expected_protected3 = -5;
+
+asm (".protected protected3");
+
+void
+set_protected1b (int i)
+{
+  protected1 = i;
+}
+
+int *
+protected1b_p (void)
+{
+  return &protected1;
+}
+
+void
+set_expected_protected3b (int i)
+{
+  expected_protected3 = i;
+}
+
+void
+set_protected3b (int i)
+{
+  protected3 = i;
+  set_expected_protected3b (i);
+}
+
+int
+check_protected3b (void)
+{
+  return protected3 == expected_protected3;
+}
+
+int *
+protected3b_p (void)
+{
+  return &protected3;
+}
diff --git a/REORG.TODO/elf/tst-ptrguard1-static.c b/REORG.TODO/elf/tst-ptrguard1-static.c
new file mode 100644
index 0000000000..7aff3b7b5d
--- /dev/null
+++ b/REORG.TODO/elf/tst-ptrguard1-static.c
@@ -0,0 +1 @@
+#include "tst-ptrguard1.c"
diff --git a/REORG.TODO/elf/tst-ptrguard1.c b/REORG.TODO/elf/tst-ptrguard1.c
new file mode 100644
index 0000000000..8ea65bb0bb
--- /dev/null
+++ b/REORG.TODO/elf/tst-ptrguard1.c
@@ -0,0 +1,217 @@
+/* Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+/* Requires _GNU_SOURCE  */
+#include <getopt.h>
+
+#ifndef POINTER_CHK_GUARD
+extern uintptr_t __pointer_chk_guard;
+# define POINTER_CHK_GUARD __pointer_chk_guard
+#endif
+
+static const char *command;
+static bool child;
+static uintptr_t ptr_chk_guard_copy;
+static bool ptr_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  ptr_chk_guard_copy = POINTER_CHK_GUARD;
+  ptr_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (!ptr_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+    {
+      puts ("POINTER_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      write (2, &ptr_chk_guard_copy, sizeof (ptr_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_ptr_chk_guards[N + 1];
+  child_ptr_chk_guards[N] = ptr_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+	{
+	  printf ("couldn't create pipe: %m\n");
+	  return 1;
+	}
+
+      pid_t pid = fork ();
+      if (pid < 0)
+	{
+	  printf ("fork failed: %m\n");
+	  return 1;
+	}
+
+      if (!pid)
+	{
+	  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+	    {
+	      puts ("POINTER_CHK_GUARD changed after fork");
+	      exit (1);
+	    }
+
+	  close (fds[0]);
+	  close (2);
+	  dup2 (fds[1], 2);
+	  close (fds[1]);
+
+	  system (command);
+	  exit (0);
+	}
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_ptr_chk_guards[i],
+				    sizeof (uintptr_t))) != sizeof (uintptr_t))
+	{
+	  puts ("could not read ptr_chk_guard value from child");
+	  return 1;
+	}
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+	{
+	  printf ("waitpid failed: %m\n");
+	  return 1;
+	}
+      else if (termpid != pid)
+	{
+	  printf ("waitpid returned %ld != %ld\n",
+		  (long int) termpid, (long int) pid);
+	  return 1;
+	}
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+	{
+	  puts ("child hasn't exited with exit status 0");
+	  return 1;
+	}
+    }
+
+  qsort (child_ptr_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  /* The default pointer guard is the same as the default stack guard.
+     They are only set to default if dl_random is NULL.  */
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the pointer guard canaries are either randomized,
+     or equal to the default pointer guard value.
+     Even with randomized pointer guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_ptr_chk_guards[i] != child_ptr_chk_guards[i+1])
+	ndifferences++;
+      else if (child_ptr_chk_guards[i] == default_guard)
+	ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("pointer guard values are not randomized enough");
+      puts ("nor equal to the default value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND	10000
+#define OPT_CHILD	10001
+#define CMDLINE_OPTIONS	\
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+
+static void __attribute((used))
+cmdline_process_function (int c)
+{
+  switch (c)
+    {
+      case OPT_COMMAND:
+        command = optarg;
+        break;
+      case OPT_CHILD:
+        child = true;
+        break;
+    }
+}
+
+#define CMDLINE_PROCESS	cmdline_process_function
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-relsort1.c b/REORG.TODO/elf/tst-relsort1.c
new file mode 100644
index 0000000000..775c968e1f
--- /dev/null
+++ b/REORG.TODO/elf/tst-relsort1.c
@@ -0,0 +1,18 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+  const char lib[] = "$ORIGIN/tst-relsort1mod1.so";
+  void *h = dlopen (lib, RTLD_NOW);
+  if (h == NULL)
+    {
+      puts (dlerror ());
+      return 1;
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-relsort1mod1.c b/REORG.TODO/elf/tst-relsort1mod1.c
new file mode 100644
index 0000000000..9e4a94321d
--- /dev/null
+++ b/REORG.TODO/elf/tst-relsort1mod1.c
@@ -0,0 +1,7 @@
+extern int foo (double);
+
+int
+bar (void)
+{
+  return foo (1.2);
+}
diff --git a/REORG.TODO/elf/tst-relsort1mod2.c b/REORG.TODO/elf/tst-relsort1mod2.c
new file mode 100644
index 0000000000..a2c3e551e4
--- /dev/null
+++ b/REORG.TODO/elf/tst-relsort1mod2.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+int
+foo (double d)
+{
+  return floor (d) != 0.0;
+}
diff --git a/REORG.TODO/elf/tst-rtld-load-self.sh b/REORG.TODO/elf/tst-rtld-load-self.sh
new file mode 100755
index 0000000000..e05f6d145f
--- /dev/null
+++ b/REORG.TODO/elf/tst-rtld-load-self.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# Test how rtld loads itself.
+# Copyright (C) 2012-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+rtld=$1
+test_wrapper=$2
+test_wrapper_env=$3
+result=0
+
+echo '# normal mode'
+${test_wrapper} $rtld $rtld 2>&1 && rc=0 || rc=$?
+echo "# exit status $rc"
+test $rc -le 127 || result=1
+
+echo '# list mode'
+${test_wrapper} $rtld --list $rtld 2>&1 && rc=0 || rc=$?
+echo "# exit status $rc"
+test $rc -eq 0 || result=1
+
+echo '# verify mode'
+${test_wrapper} $rtld --verify $rtld 2>&1 && rc=0 || rc=$?
+echo "# exit status $rc"
+test $rc -eq 2 || result=1
+
+echo '# trace mode'
+${test_wrapper_env} LD_TRACE_LOADED_OBJECTS=1 \
+    $rtld $rtld 2>&1 && rc=0 || rc=$?
+echo "# exit status $rc"
+test $rc -eq 0 || result=1
+
+exit $result
diff --git a/REORG.TODO/elf/tst-stackguard1-static.c b/REORG.TODO/elf/tst-stackguard1-static.c
new file mode 100644
index 0000000000..db1e21554d
--- /dev/null
+++ b/REORG.TODO/elf/tst-stackguard1-static.c
@@ -0,0 +1 @@
+#include "tst-stackguard1.c"
diff --git a/REORG.TODO/elf/tst-stackguard1.c b/REORG.TODO/elf/tst-stackguard1.c
new file mode 100644
index 0000000000..78e33c7083
--- /dev/null
+++ b/REORG.TODO/elf/tst-stackguard1.c
@@ -0,0 +1,205 @@
+/* Copyright (C) 2005-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+static const char *command;
+static bool child;
+static uintptr_t stack_chk_guard_copy;
+static bool stack_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  stack_chk_guard_copy = STACK_CHK_GUARD;
+  stack_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (!stack_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (stack_chk_guard_copy != STACK_CHK_GUARD)
+    {
+      puts ("STACK_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_stack_chk_guards[N + 1];
+  child_stack_chk_guards[N] = stack_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+	{
+	  printf ("couldn't create pipe: %m\n");
+	  return 1;
+	}
+
+      pid_t pid = fork ();
+      if (pid < 0)
+	{
+	  printf ("fork failed: %m\n");
+	  return 1;
+	}
+
+      if (!pid)
+	{
+	  if (stack_chk_guard_copy != STACK_CHK_GUARD)
+	    {
+	      puts ("STACK_CHK_GUARD changed after fork");
+	      exit (1);
+	    }
+
+	  close (fds[0]);
+	  close (2);
+	  dup2 (fds[1], 2);
+	  close (fds[1]);
+
+	  system (command);
+	  exit (0);
+	}
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
+				    sizeof (uintptr_t))) != sizeof (uintptr_t))
+	{
+	  puts ("could not read stack_chk_guard value from child");
+	  return 1;
+	}
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+	{
+	  printf ("waitpid failed: %m\n");
+	  return 1;
+	}
+      else if (termpid != pid)
+	{
+	  printf ("waitpid returned %ld != %ld\n",
+		  (long int) termpid, (long int) pid);
+	  return 1;
+	}
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+	{
+	  puts ("child hasn't exited with exit status 0");
+	  return 1;
+	}
+    }
+
+  qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the stack guard canaries are either randomized,
+     or equal to the default stack guard canary value.
+     Even with randomized stack guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
+	ndifferences++;
+      else if (child_stack_chk_guards[i] == default_guard)
+	ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("stack guard canaries are not randomized enough");
+      puts ("nor equal to the default canary value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND	10000
+#define OPT_CHILD	10001
+#define CMDLINE_OPTIONS	\
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+
+static void __attribute__((used))
+cmdline_process_function (int c)
+{
+  switch (c)
+    {
+      case OPT_COMMAND:
+        command = optarg;
+        break;
+      case OPT_CHILD:
+        child = true;
+        break;
+    }
+}
+#define CMDLINE_PROCESS	cmdline_process_function
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-thrlock.c b/REORG.TODO/elf/tst-thrlock.c
new file mode 100644
index 0000000000..1beffc3861
--- /dev/null
+++ b/REORG.TODO/elf/tst-thrlock.c
@@ -0,0 +1,58 @@
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnu/lib-names.h>
+
+static void *
+tf (void *arg)
+{
+  void *h = dlopen (LIBM_SO, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("dlopen failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlsym (h, "sin") == NULL)
+    {
+      printf ("dlsym failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlclose (h) != 0)
+    {
+      printf ("dlclose failed: %s\n", dlerror ());
+      exit (1);
+    }
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+#define N 10
+  pthread_t th[N];
+  for (int i = 0; i < N; ++i)
+    {
+      int e = pthread_create (&th[i], NULL, tf, NULL);
+      if (e != 0)
+	{
+	  printf ("pthread_create failed with %d (%s)\n", e, strerror (e));
+	  return 1;
+	}
+    }
+  for (int i = 0; i < N; ++i)
+    {
+      void *res;
+      int e = pthread_join (th[i], &res);
+      if (e != 0 || res != NULL)
+	{
+	  puts ("thread failed");
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls-dlinfo.c b/REORG.TODO/elf/tst-tls-dlinfo.c
new file mode 100644
index 0000000000..7d2b42e2ab
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls-dlinfo.c
@@ -0,0 +1,85 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-tlsmod2.so";
+  int result = 0;
+  int *foop;
+  int (*fp) (int, int *);
+  void *h;
+
+  h = dlopen (modname, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname, dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
+      exit (1);
+    }
+
+  size_t modid = -1;
+  if (dlinfo (h, RTLD_DI_TLS_MODID, &modid))
+    {
+      printf ("dlinfo RTLD_DI_TLS_MODID failed: %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    printf ("dlinfo says TLS module ID %Zu\n", modid);
+
+  void *block;
+  if (dlinfo (h, RTLD_DI_TLS_DATA, &block))
+    {
+      printf ("dlinfo RTLD_DI_TLS_DATA failed: %s\n", dlerror ());
+      result = 1;
+    }
+  else if (block != NULL)
+    {
+      printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be unallocated\n",
+	      block);
+      result = 1;
+    }
+
+  result |= fp (0, NULL);
+
+  foop = dlsym (h, "foo");
+  if (foop == NULL)
+    {
+      printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ());
+      exit (1);
+    }
+  if (*foop != 16)
+    {
+      puts ("foo != 16");
+      result = 1;
+    }
+
+  /* Now the module's TLS block has been used and should appear.  */
+  if (dlinfo (h, RTLD_DI_TLS_DATA, &block))
+    {
+      printf ("dlinfo RTLD_DI_TLS_DATA failed the second time: %s\n",
+	      dlerror ());
+      result = 1;
+    }
+  else if (block != foop)
+    {
+      printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be %p\n",
+	      block, foop);
+      result = 1;
+    }
+
+  dlclose (h);
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls-manydynamic.c b/REORG.TODO/elf/tst-tls-manydynamic.c
new file mode 100644
index 0000000000..b072d0be68
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls-manydynamic.c
@@ -0,0 +1,151 @@
+/* Test with many dynamic TLS variables.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This test intends to exercise dynamic TLS variable allocation.  It
+   achieves this by combining dlopen (to avoid static TLS allocation
+   after static TLS resizing), many DSOs with a large variable (to
+   exceed the static TLS reserve), and an already-running thread (to
+   force full dynamic TLS initialization).  */
+
+#include "tst-tls-manydynamic.h"
+
+#include <errno.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int do_test (void);
+#include <support/xthread.h>
+#include <support/test-driver.c>
+
+void *handles[COUNT];
+set_value_func set_value_funcs[COUNT];
+get_value_func get_value_funcs[COUNT];
+
+static void
+init_functions (void)
+{
+  for (int i = 0; i < COUNT; ++i)
+    {
+      /* Open the module.  */
+      {
+        char soname[100];
+        snprintf (soname, sizeof (soname), "tst-tls-manydynamic%02dmod.so", i);
+        handles[i] = dlopen (soname, RTLD_LAZY);
+        if (handles[i] == NULL)
+          {
+            printf ("error: dlopen failed: %s\n", dlerror ());
+            exit (1);
+          }
+      }
+
+      /* Obtain the setter function.  */
+      {
+        char fname[100];
+        snprintf (fname, sizeof (fname), "set_value_%02d", i);
+        void *func = dlsym (handles[i], fname);
+        if (func == NULL)
+          {
+            printf ("error: dlsym: %s\n", dlerror ());
+            exit (1);
+          }
+        set_value_funcs[i] = func;
+      }
+
+      /* Obtain the getter function.  */
+      {
+        char fname[100];
+        snprintf (fname, sizeof (fname), "get_value_%02d", i);
+        void *func = dlsym (handles[i], fname);
+        if (func == NULL)
+          {
+            printf ("error: dlsym: %s\n", dlerror ());
+            exit (1);
+          }
+        get_value_funcs[i] = func;
+      }
+    }
+}
+
+static pthread_barrier_t barrier;
+
+/* Running thread which forces real TLS initialization.  */
+static void *
+blocked_thread_func (void *closure)
+{
+  xpthread_barrier_wait (&barrier);
+
+  /* TLS test runs here in the main thread.  */
+
+  xpthread_barrier_wait (&barrier);
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  {
+    int ret = pthread_barrier_init (&barrier, NULL, 2);
+    if (ret != 0)
+      {
+        errno = ret;
+        printf ("error: pthread_barrier_init: %m\n");
+        exit (1);
+      }
+  }
+
+  pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL);
+  xpthread_barrier_wait (&barrier);
+
+  init_functions ();
+
+  struct value values[COUNT];
+  /* Initialze the TLS variables.  */
+  for (int i = 0; i < COUNT; ++i)
+    {
+      for (int j = 0; j < PER_VALUE_COUNT; ++j)
+        values[i].num[j] = rand ();
+      set_value_funcs[i] (&values[i]);
+    }
+
+  /* Read back their values to check that they do not overlap.  */
+  for (int i = 0; i < COUNT; ++i)
+    {
+      struct value actual;
+      get_value_funcs[i] (&actual);
+
+      for (int j = 0; j < PER_VALUE_COUNT; ++j)
+        if (actual.num[j] != values[i].num[j])
+        {
+          printf ("error: mismatch at variable %d/%d: %d != %d\n",
+                  i, j, actual.num[j], values[i].num[j]);
+          exit (1);
+        }
+    }
+
+  xpthread_barrier_wait (&barrier);
+  xpthread_join (blocked_thread);
+
+  /* Close the modules.  */
+  for (int i = 0; i < COUNT; ++i)
+    dlclose (handles[i]);
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-tls-manydynamic.h b/REORG.TODO/elf/tst-tls-manydynamic.h
new file mode 100644
index 0000000000..13fac4e7e8
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls-manydynamic.h
@@ -0,0 +1,44 @@
+/* Interfaces for test with many dynamic TLS variables.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef TST_TLS_MANYDYNAMIC_H
+#define TST_TLS_MANYDYNAMIC_H
+
+enum
+  {
+    /* This many TLS variables (and modules) are defined.  */
+    COUNT = 100,
+
+    /* Number of elements in the TLS variable.  */
+    PER_VALUE_COUNT = 1,
+  };
+
+/* The TLS variables are of this type.  We use a larger type to ensure
+   that we can reach the static TLS limit with COUNT variables.  */
+struct value
+{
+  int num[PER_VALUE_COUNT];
+};
+
+/* Set the TLS variable defined in the module.  */
+typedef void (*set_value_func) (const struct value *);
+
+/* Read the TLS variable defined in the module.  */
+typedef void (*get_value_func) (struct value *);
+
+#endif /* TST_TLS_MANYDYNAMICMOD_H */
diff --git a/REORG.TODO/elf/tst-tls-manydynamicmod.c b/REORG.TODO/elf/tst-tls-manydynamicmod.c
new file mode 100644
index 0000000000..edfaeef7f3
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls-manydynamicmod.c
@@ -0,0 +1,36 @@
+/* Module for test with many dynamic TLS variables.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is parameterized by macros NAME, SETTER, GETTER, which
+   are set form the Makefile.  */
+
+#include "tst-tls-manydynamic.h"
+
+__thread struct value NAME;
+
+void
+SETTER (const struct value *value)
+{
+  NAME = *value;
+}
+
+void
+GETTER (struct value *value)
+{
+  *value = NAME;
+}
diff --git a/REORG.TODO/elf/tst-tls1-static.c b/REORG.TODO/elf/tst-tls1-static.c
new file mode 100644
index 0000000000..a01008073b
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls1-static.c
@@ -0,0 +1 @@
+#include "tst-tls1.c"
diff --git a/REORG.TODO/elf/tst-tls1.c b/REORG.TODO/elf/tst-tls1.c
new file mode 100644
index 0000000000..c31da56ce9
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls1.c
@@ -0,0 +1,82 @@
+/* glibc test for TLS in ld.so.  */
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+/* Two common 'int' variables in TLS.  */
+COMMON_INT_DEF(foo);
+COMMON_INT_DEF(bar);
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  int *ap, *bp;
+
+
+  /* Set the variable using the local exec model.  */
+  puts ("set bar to 1 (LE)");
+  ap = TLS_LE (bar);
+  *ap = 1;
+
+
+  /* Get variables using initial exec model.  */
+  fputs ("get sum of foo and bar (IE)", stdout);
+  ap = TLS_IE (foo);
+  bp = TLS_IE (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+
+  /* Get variables using local dynamic model.  */
+  fputs ("get sum of foo and bar (LD)", stdout);
+  ap = TLS_LD (foo);
+  bp = TLS_LD (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+
+  /* Get variables using generic dynamic model.  */
+  fputs ("get sum of foo and bar (GD)", stdout);
+  ap = TLS_GD (foo);
+  bp = TLS_GD (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls10.c b/REORG.TODO/elf/tst-tls10.c
new file mode 100644
index 0000000000..d9611aac6d
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls10.c
@@ -0,0 +1,39 @@
+#include "tst-tls10.h"
+
+__thread int dummy __attribute__((visibility ("hidden"))) = 12;
+__thread struct A local = { 1, 2, 3 };
+
+#define CHECK(N, S)					\
+  p = f##N##a ();					\
+  if (p->a != S || p->b != S + 1 || p->c != S + 2)	\
+    abort ()
+
+static int
+do_test (void)
+{
+  struct A *p;
+  if (local.a != 1 || local.b != 2 || local.c != 3)
+    abort ();
+  if (a1.a != 4 || a1.b != 5 || a1.c != 6)
+    abort ();
+  if (a2.a != 22 || a2.b != 23 || a2.c != 24)
+    abort ();
+  if (a3.a != 10 || a3.b != 11 || a3.c != 12)
+    abort ();
+  if (a4.a != 25 || a4.b != 26 || a4.c != 27)
+    abort ();
+  check1 ();
+  check2 ();
+  if (f1a () != &a1 || f2a () != &a2 || f3a () != &a3 || f4a () != &a4)
+    abort ();
+  CHECK (5, 16);
+  CHECK (6, 19);
+  if (f7a () != &a2 || f8a () != &a4)
+    abort ();
+  CHECK (9, 28);
+  CHECK (10, 31);
+
+  exit (0);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls10.h b/REORG.TODO/elf/tst-tls10.h
new file mode 100644
index 0000000000..7c8c6a6391
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls10.h
@@ -0,0 +1,32 @@
+#include <stdlib.h>
+
+struct A
+{
+  char a;
+  int b;
+  long long c;
+};
+
+extern __thread struct A a1, a2, a3, a4;
+extern struct A *f1a (void);
+extern struct A *f2a (void);
+extern struct A *f3a (void);
+extern struct A *f4a (void);
+extern struct A *f5a (void);
+extern struct A *f6a (void);
+extern struct A *f7a (void);
+extern struct A *f8a (void);
+extern struct A *f9a (void);
+extern struct A *f10a (void);
+extern int f1b (void);
+extern int f2b (void);
+extern int f3b (void);
+extern int f4b (void);
+extern int f5b (void);
+extern int f6b (void);
+extern int f7b (void);
+extern int f8b (void);
+extern int f9b (void);
+extern int f10b (void);
+extern void check1 (void);
+extern void check2 (void);
diff --git a/REORG.TODO/elf/tst-tls11.c b/REORG.TODO/elf/tst-tls11.c
new file mode 100644
index 0000000000..a5c3dd70b0
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls11.c
@@ -0,0 +1,28 @@
+#include "tst-tls10.h"
+
+#define CHECK(N, S)					\
+  p = f##N##a ();					\
+  if (p->a != S || p->b != S + 1 || p->c != S + 2)	\
+    abort ()
+
+static int
+do_test (void)
+{
+  struct A *p;
+  check1 ();
+  check2 ();
+  CHECK (1, 4);
+  CHECK (2, 22);
+  CHECK (3, 10);
+  CHECK (4, 25);
+  CHECK (5, 16);
+  CHECK (6, 19);
+  CHECK (7, 22);
+  CHECK (8, 25);
+  CHECK (9, 28);
+  CHECK (10, 31);
+
+  exit (0);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls12.c b/REORG.TODO/elf/tst-tls12.c
new file mode 100644
index 0000000000..ccd5f8b43e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls12.c
@@ -0,0 +1,19 @@
+#include "tst-tls10.h"
+
+#define CHECK(N, S)					\
+  p = &a##N;						\
+  if (p->a != S || p->b != S + 1 || p->c != S + 2)	\
+    abort ()
+
+static int
+do_test (void)
+{
+  struct A *p;
+  check1 ();
+  CHECK (1, 4);
+  CHECK (2, 7);
+
+  exit (0);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls13.c b/REORG.TODO/elf/tst-tls13.c
new file mode 100644
index 0000000000..b1d303310f
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls13.c
@@ -0,0 +1,28 @@
+/* Check unloading modules with data in static TLS block.  */
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int
+do_test (void)
+{
+  for (int i = 0; i < 1000;)
+    {
+      printf ("round %d\n",++i);
+
+      void *h = dlopen ("$ORIGIN/tst-tlsmod13a.so", RTLD_LAZY);
+      if (h == NULL)
+	{
+	  printf ("cannot load: %s\n", dlerror ());
+	  exit (1);
+	}
+
+      dlclose (h);
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls14.c b/REORG.TODO/elf/tst-tls14.c
new file mode 100644
index 0000000000..a6a79ef24f
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls14.c
@@ -0,0 +1,54 @@
+/* Check alignment of TLS variable.  */
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define AL 4096
+struct foo
+{
+  int i;
+} __attribute ((aligned (AL)));
+
+static __thread struct foo f;
+static struct foo g;
+
+
+extern int in_dso1 (void);
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  int fail = (((uintptr_t) &f) & (AL - 1)) != 0;
+  printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK");
+  result |= fail;
+
+  fail = (((uintptr_t) &g) & (AL - 1)) != 0;
+  printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK");
+  result |= fail;
+
+  result |= in_dso1 ();
+
+  void *h = dlopen ("tst-tlsmod14b.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open tst-tlsmod14b.so: %m\n");
+      exit (1);
+    }
+
+  int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso2");
+  if (fp == NULL)
+    {
+      puts ("cannot find in_dso2");
+      exit (1);
+    }
+
+  result |= fp ();
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls15.c b/REORG.TODO/elf/tst-tls15.c
new file mode 100644
index 0000000000..db2a4f4b77
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls15.c
@@ -0,0 +1,32 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen ("tst-tlsmod15a.so", RTLD_NOW);
+  if (h != NULL)
+    {
+      puts ("unexpectedly succeeded to open tst-tlsmod15a.so");
+      exit (1);
+    }
+
+  h = dlopen ("tst-tlsmod15b.so", RTLD_NOW);
+  if (h == NULL)
+    {
+      puts ("failed to open tst-tlsmod15b.so");
+      exit (1);
+    }
+
+  int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      puts ("cannot find in_dso");
+      exit (1);
+    }
+
+  return fp ();
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls16.c b/REORG.TODO/elf/tst-tls16.c
new file mode 100644
index 0000000000..f2830b8a4f
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls16.c
@@ -0,0 +1,52 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen ("tst-tlsmod16a.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h == NULL)
+    {
+      puts ("unexpectedly failed to open tst-tlsmod16a.so");
+      exit (1);
+    }
+
+  void *p = dlsym (h, "tlsvar");
+
+  /* This dlopen should indeed fail, because tlsvar was assigned to
+     dynamic TLS, and the new module requests it to be in static TLS.
+     However, there's a possibility that dlopen succeeds if the
+     variable is, for whatever reason, assigned to static TLS, or if
+     the module fails to require static TLS, or even if TLS is not
+     supported.  */
+  h = dlopen ("tst-tlsmod16b.so", RTLD_NOW | RTLD_GLOBAL);
+  if (h == NULL)
+    {
+      return 0;
+    }
+
+  puts ("unexpectedly succeeded to open tst-tlsmod16b.so");
+
+
+  void *(*fp) (void) = (void *(*) (void)) dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      puts ("cannot find in_dso");
+      exit (1);
+    }
+
+  /* If the dlopen passes, at least make sure the address returned by
+     dlsym is the same as that returned by the initial-exec access.
+     If the variable was assigned to dynamic TLS during dlsym, this
+     portion will fail.  */
+  if (fp () != p)
+    {
+      puts ("returned values do not match");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls17.c b/REORG.TODO/elf/tst-tls17.c
new file mode 100644
index 0000000000..c2a972d3c4
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls17.c
@@ -0,0 +1,28 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen ("tst-tlsmod17b.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("unexpectedly failed to open tst-tlsmod17b.so");
+      exit (1);
+    }
+
+  int (*fp) (void) = (int (*) (void)) dlsym (h, "tlsmod17b");
+  if (fp == NULL)
+    {
+      puts ("cannot find tlsmod17b");
+      exit (1);
+    }
+
+  if (fp ())
+    exit (1);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls18.c b/REORG.TODO/elf/tst-tls18.c
new file mode 100644
index 0000000000..b705b61d60
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls18.c
@@ -0,0 +1,37 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  char modname[sizeof "tst-tlsmod18aXX.so"];
+  void *h[20];
+  for (int i = 0; i < 20; i++)
+    {
+      snprintf (modname, sizeof modname, "tst-tlsmod18a%d.so", i);
+      h[i] = dlopen (modname, RTLD_LAZY);
+      if (h[i] == NULL)
+	{
+	  printf ("unexpectedly failed to open %s", modname);
+	  exit (1);
+	}
+    }
+
+  for (int i = 0; i < 20; i++)
+    {
+      int (*fp) (void) = (int (*) (void)) dlsym (h[i], "test");
+      if (fp == NULL)
+	{
+	  printf ("cannot find test in tst-tlsmod18a%d.so", i);
+	  exit (1);
+	}
+
+      if (fp ())
+	exit (1);
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls19.c b/REORG.TODO/elf/tst-tls19.c
new file mode 100644
index 0000000000..dd8ea42c3f
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls19.c
@@ -0,0 +1,26 @@
+// BZ 12453
+#include <stdio.h>
+#include <dlfcn.h>
+
+
+static int
+do_test (void)
+{
+  void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (dl == NULL)
+    {
+      printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ());
+      return 1;
+    }
+
+  int (*fn) (void) = dlsym (dl, "foo");
+  if (fn == NULL)
+    {
+      printf("Error obtaining symbol foo\n");
+      return 1;
+    }
+
+  return fn ();
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls19mod1.c b/REORG.TODO/elf/tst-tls19mod1.c
new file mode 100644
index 0000000000..2790097ae5
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls19mod1.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+extern int bar (void);
+extern int baz (void);
+
+int
+foo (void)
+{
+  int v1 = bar ();
+  int v2 = baz ();
+
+  printf ("bar=%d, baz=%d\n", v1, v2);
+
+  return v1 != 666 || v2 != 42;
+}
diff --git a/REORG.TODO/elf/tst-tls19mod2.c b/REORG.TODO/elf/tst-tls19mod2.c
new file mode 100644
index 0000000000..cae702f67c
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls19mod2.c
@@ -0,0 +1,13 @@
+static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666;
+
+void
+setter (int a)
+{
+  tbar = a;
+}
+
+int
+bar (void)
+{
+  return tbar;
+}
diff --git a/REORG.TODO/elf/tst-tls19mod3.c b/REORG.TODO/elf/tst-tls19mod3.c
new file mode 100644
index 0000000000..e7b28016b3
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls19mod3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42;
+
+void
+setter2 (int a)
+{
+  tbaz = a;
+}
+
+int
+baz (void)
+{
+  printf ("&tbaz=%p\n", &tbaz);
+  return tbaz;
+}
diff --git a/REORG.TODO/elf/tst-tls2-static.c b/REORG.TODO/elf/tst-tls2-static.c
new file mode 100644
index 0000000000..55ffa57448
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls2-static.c
@@ -0,0 +1 @@
+#include "tst-tls2.c"
diff --git a/REORG.TODO/elf/tst-tls2.c b/REORG.TODO/elf/tst-tls2.c
new file mode 100644
index 0000000000..963b8d6c88
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls2.c
@@ -0,0 +1,82 @@
+/* glibc test for TLS in ld.so.  */
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+/* Two 'int' variables in TLS.  */
+VAR_INT_DEF(foo);
+VAR_INT_DEF(bar);
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  int *ap, *bp;
+
+
+  /* Set the variable using the local exec model.  */
+  puts ("set bar to 1 (LE)");
+  ap = TLS_LE (bar);
+  *ap = 1;
+
+
+  /* Get variables using initial exec model.  */
+  fputs ("get sum of foo and bar (IE)", stdout);
+  ap = TLS_IE (foo);
+  bp = TLS_IE (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+
+  /* Get variables using local dynamic model.  */
+  fputs ("get sum of foo and bar (LD)", stdout);
+  ap = TLS_LD (foo);
+  bp = TLS_LD (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+
+  /* Get variables using generic dynamic model.  */
+  fputs ("get sum of foo and bar (GD)", stdout);
+  ap = TLS_GD (foo);
+  bp = TLS_GD (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 1;
+  if (*ap != 0)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 1)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls3.c b/REORG.TODO/elf/tst-tls3.c
new file mode 100644
index 0000000000..7e0abb4c58
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls3.c
@@ -0,0 +1,67 @@
+/* glibc test for TLS in ld.so.  */
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+/* One define int variable, two externs.  */
+COMMON_INT_DECL(foo);
+VAR_INT_DECL(bar);
+VAR_INT_DEF(baz);
+
+
+extern int in_dso (void);
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  int *ap, *bp, *cp;
+
+
+  /* Set the variable using the local exec model.  */
+  puts ("set baz to 3 (LE)");
+  ap = TLS_LE (baz);
+  *ap = 3;
+
+
+  /* Get variables using initial exec model.  */
+  puts ("set variables foo and bar (IE)");
+  ap = TLS_IE (foo);
+  *ap = 1;
+  bp = TLS_IE (bar);
+  *bp = 2;
+
+
+  /* Get variables using local dynamic model.  */
+  fputs ("get sum of foo, bar (GD) and baz (LD)", stdout);
+  ap = TLS_GD (foo);
+  bp = TLS_GD (bar);
+  cp = TLS_LD (baz);
+  printf (" = %d\n", *ap + *bp + *cp);
+  result |= *ap + *bp + *cp != 6;
+  if (*ap != 1)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 2)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+  if (*cp != 3)
+    {
+      printf ("baz = %d\n", *cp);
+      result = 1;
+    }
+
+
+  result |= in_dso ();
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls4.c b/REORG.TODO/elf/tst-tls4.c
new file mode 100644
index 0000000000..6841f81386
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls4.c
@@ -0,0 +1,49 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-tlsmod2.so";
+  int result = 0;
+  int *foop;
+  int (*fp) (int, int *);
+  void *h;
+
+  h = dlopen (modname, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname, dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
+      exit (1);
+    }
+
+  result |= fp (0, NULL);
+
+  foop = dlsym (h, "foo");
+  if (foop == NULL)
+    {
+      printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ());
+      exit (1);
+    }
+  if (*foop != 16)
+    {
+      puts ("foo != 16");
+      result = 1;
+    }
+
+  dlclose (h);
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls5.c b/REORG.TODO/elf/tst-tls5.c
new file mode 100644
index 0000000000..5f006fd645
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls5.c
@@ -0,0 +1,65 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-tlsmod2.so";
+  int result = 0;
+  int *foop;
+  int *foop2;
+  int (*fp) (int, int *);
+  void *h;
+
+  h = dlopen (modname, RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname, dlerror ());
+      exit (1);
+    }
+
+  foop = dlsym (h, "foo");
+  if (foop == NULL)
+    {
+      printf ("cannot get symbol 'foo': %s\n", dlerror ());
+      exit (1);
+    }
+
+  *foop = 42;
+
+  fp = dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
+      exit (1);
+    }
+
+  result |= fp (42, foop);
+
+  foop2 = dlsym (h, "foo");
+  if (foop2 == NULL)
+    {
+      printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  if (foop != foop2)
+    {
+      puts ("address of 'foo' different the second time");
+      result = 1;
+    }
+  else if (*foop != 16)
+    {
+      puts ("foo != 16");
+      result = 1;
+    }
+
+  dlclose (h);
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls6.c b/REORG.TODO/elf/tst-tls6.c
new file mode 100644
index 0000000000..df81c1f6b4
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls6.c
@@ -0,0 +1,84 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <link.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-tlsmod2.so";
+  int result = 0;
+  int *foop;
+  int *foop2;
+  int (*fp) (int, int *);
+  void *h;
+  int i;
+  int modid = -1;
+
+  for (i = 0; i < 10; ++i)
+    {
+      h = dlopen (modname, RTLD_LAZY);
+      if (h == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (modid == -1)
+	modid = ((struct link_map *) h)->l_tls_modid;
+      else if (((struct link_map *) h)->l_tls_modid != modid)
+	{
+	  printf ("round %d: modid now %zd, initially %d\n",
+		  i, ((struct link_map *) h)->l_tls_modid, modid);
+	  result = 1;
+	}
+
+      foop = dlsym (h, "foo");
+      if (foop == NULL)
+	{
+	  printf ("cannot get symbol 'foo': %s\n", dlerror ());
+	  exit (1);
+	}
+
+      *foop = 42 + i;
+
+      fp = dlsym (h, "in_dso");
+      if (fp == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
+	  exit (1);
+	}
+
+      result |= fp (42 + i, foop);
+
+      foop2 = dlsym (h, "foo");
+      if (foop2 == NULL)
+	{
+	  printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ());
+	  exit (1);
+	}
+
+      if (foop != foop2)
+	{
+	  puts ("address of 'foo' different the second time");
+	  result = 1;
+	}
+      else if (*foop != 16)
+	{
+	  puts ("foo != 16");
+	  result = 1;
+	}
+
+      dlclose (h);
+    }
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls7.c b/REORG.TODO/elf/tst-tls7.c
new file mode 100644
index 0000000000..fa46709600
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls7.c
@@ -0,0 +1,55 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <link.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname[] = "tst-tlsmod3.so";
+  int result = 0;
+  int (*fp) (void);
+  void *h;
+  int i;
+  int modid = -1;
+
+  for (i = 0; i < 10; ++i)
+    {
+      h = dlopen (modname, RTLD_LAZY);
+      if (h == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (modid == -1)
+	modid = ((struct link_map *) h)->l_tls_modid;
+      else if (((struct link_map *) h)->l_tls_modid != (size_t) modid)
+	{
+	  printf ("round %d: modid now %zu, initially %d\n",
+		  i, ((struct link_map *) h)->l_tls_modid, modid);
+	  result = 1;
+	}
+
+      fp = dlsym (h, "in_dso2");
+      if (fp == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso2': %s\n", dlerror ());
+	  exit (1);
+	}
+
+      result |= fp ();
+
+      dlclose (h);
+    }
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls8.c b/REORG.TODO/elf/tst-tls8.c
new file mode 100644
index 0000000000..c779572617
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls8.c
@@ -0,0 +1,167 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <link.h>
+
+
+static int
+do_test (void)
+{
+  static const char modname1[] = "$ORIGIN/tst-tlsmod3.so";
+  static const char modname2[] = "$ORIGIN/tst-tlsmod4.so";
+  int result = 0;
+  int (*fp1) (void);
+  int (*fp2) (int, int *);
+  void *h1;
+  void *h2;
+  int i;
+  size_t modid1 = (size_t) -1;
+  size_t modid2 = (size_t) -1;
+  int *bazp;
+
+  for (i = 0; i < 10; ++i)
+    {
+      h1 = dlopen (modname1, RTLD_LAZY);
+      if (h1 == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname1, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (modid1 == (size_t) -1)
+	modid1 = ((struct link_map *) h1)->l_tls_modid;
+      else if (((struct link_map *) h1)->l_tls_modid != modid1)
+	{
+	  printf ("round %d: modid now %zd, initially %zd\n",
+		  i, ((struct link_map *) h1)->l_tls_modid, modid1);
+	  result = 1;
+	}
+
+      fp1 = dlsym (h1, "in_dso2");
+      if (fp1 == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso2' in %s\n", modname1);
+	  exit (1);
+	}
+
+      result |= fp1 ();
+
+
+
+      h2 = dlopen (modname2, RTLD_LAZY);
+      if (h2 == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname2, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (modid2 == (size_t) -1)
+	modid2 = ((struct link_map *) h1)->l_tls_modid;
+      else if (((struct link_map *) h1)->l_tls_modid != modid2)
+	{
+	  printf ("round %d: modid now %zd, initially %zd\n",
+		  i, ((struct link_map *) h1)->l_tls_modid, modid2);
+	  result = 1;
+	}
+
+      bazp = dlsym (h2, "baz");
+      if (bazp == NULL)
+	{
+	  printf ("cannot get symbol 'baz' in %s\n", modname2);
+	  exit (1);
+	}
+
+      *bazp = 42 + i;
+
+      fp2 = dlsym (h2, "in_dso");
+      if (fp2 == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso' in %s\n", modname2);
+	  exit (1);
+	}
+
+      result |= fp2 (42 + i, bazp);
+
+      dlclose (h1);
+      dlclose (h2);
+
+
+      h1 = dlopen (modname1, RTLD_LAZY);
+      if (h1 == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname1, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (((struct link_map *) h1)->l_tls_modid != modid1)
+	{
+	  printf ("round %d: modid now %zd, initially %zd\n",
+		  i, ((struct link_map *) h1)->l_tls_modid, modid1);
+	  result = 1;
+	}
+
+      fp1 = dlsym (h1, "in_dso2");
+      if (fp1 == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso2' in %s\n", modname1);
+	  exit (1);
+	}
+
+      result |= fp1 ();
+
+
+
+      h2 = dlopen (modname2, RTLD_LAZY);
+      if (h2 == NULL)
+	{
+	  printf ("cannot open '%s': %s\n", modname2, dlerror ());
+	  exit (1);
+	}
+
+      /* Dirty test code here: we peek into a private data structure.
+	 We make sure that the module gets assigned the same ID every
+	 time.  The value of the first round is used.  */
+      if (((struct link_map *) h1)->l_tls_modid != modid2)
+	{
+	  printf ("round %d: modid now %zd, initially %zd\n",
+		  i, ((struct link_map *) h1)->l_tls_modid, modid2);
+	  result = 1;
+	}
+
+      bazp = dlsym (h2, "baz");
+      if (bazp == NULL)
+	{
+	  printf ("cannot get symbol 'baz' in %s\n", modname2);
+	  exit (1);
+	}
+
+      *bazp = 62 + i;
+
+      fp2 = dlsym (h2, "in_dso");
+      if (fp2 == NULL)
+	{
+	  printf ("cannot get symbol 'in_dso' in %s\n", modname2);
+	  exit (1);
+	}
+
+      result |= fp2 (62 + i, bazp);
+
+      /* This time the dlclose calls are in reverse order.  */
+      dlclose (h2);
+      dlclose (h1);
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tls9-static.c b/REORG.TODO/elf/tst-tls9-static.c
new file mode 100644
index 0000000000..51812ccc7d
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls9-static.c
@@ -0,0 +1 @@
+#include "tst-tls9.c"
diff --git a/REORG.TODO/elf/tst-tls9.c b/REORG.TODO/elf/tst-tls9.c
new file mode 100644
index 0000000000..ee21b47c70
--- /dev/null
+++ b/REORG.TODO/elf/tst-tls9.c
@@ -0,0 +1,36 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <link.h>
+
+static int
+do_test (void)
+{
+  static const char modname1[] = "tst-tlsmod5.so";
+  static const char modname2[] = "tst-tlsmod6.so";
+  int result = 0;
+
+  void *h1 = dlopen (modname1, RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname1, dlerror ());
+      result = 1;
+    }
+  void *h2 = dlopen (modname2, RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open '%s': %s\n", modname2, dlerror ());
+      result = 1;
+    }
+
+  if (h1 != NULL)
+    dlclose (h1);
+  if (h2 != NULL)
+    dlclose (h2);
+
+  return result;
+}
+
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tlsalign-extern-static.c b/REORG.TODO/elf/tst-tlsalign-extern-static.c
new file mode 100644
index 0000000000..e84900eee4
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign-extern-static.c
@@ -0,0 +1 @@
+#include "tst-tlsalign-extern.c"
diff --git a/REORG.TODO/elf/tst-tlsalign-extern.c b/REORG.TODO/elf/tst-tlsalign-extern.c
new file mode 100644
index 0000000000..11384d085e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign-extern.c
@@ -0,0 +1,73 @@
+/* Test for large alignment in TLS blocks (extern case), BZ#18383.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* This is the same as tst-tlsalign-static.c, except that it uses
+   TLS variables that are defined in a separate translation unit
+   (ts-tlsalign-vars.c).  It turned out that the cause of BZ#18383
+   on ARM was actually an ARM assembler bug triggered by the ways of
+   using .tdata/.tbss sections and relocs referring to them that GCC
+   chooses when the variables are defined in the same translation
+   unit that contains the references.  */
+
+extern __thread int tdata1;
+extern __thread int tdata2;
+extern __thread int tdata3;
+extern __thread int tbss1;
+extern __thread int tbss2;
+extern __thread int tbss3;
+
+static int
+test_one (const char *which, unsigned int alignment, int *var, int value)
+{
+  uintptr_t addr = (uintptr_t) var;
+  unsigned int misalign = addr & (alignment - 1);
+
+  printf ("%s TLS address %p %% %u = %u\n",
+	  which, (void *) var, alignment, misalign);
+
+  int got = *var;
+  if (got != value)
+    {
+      printf ("%s value %d should be %d\n", which, got, value);
+      return 1;
+    }
+
+  return misalign != 0;
+}
+
+static int
+do_test (void)
+{
+  int fail = 0;
+
+  fail |= test_one ("tdata1", 4, &tdata1, 1);
+  fail |= test_one ("tdata2", 0x10, &tdata2, 2);
+  fail |= test_one ("tdata3", 0x1000, &tdata3, 4);
+
+  fail |= test_one ("tbss1", 4, &tbss1, 0);
+  fail |= test_one ("tbss2", 0x10, &tbss2, 0);
+  fail |= test_one ("tbss3", 0x1000, &tbss3, 0);
+
+  return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tlsalign-lib.c b/REORG.TODO/elf/tst-tlsalign-lib.c
new file mode 100644
index 0000000000..4371e581a6
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign-lib.c
@@ -0,0 +1,6 @@
+__thread int mod_tdata1 = 1;
+__thread int mod_tdata2 __attribute__ ((aligned (0x10))) = 2;
+__thread int mod_tdata3 __attribute__ ((aligned (0x1000))) = 4;
+__thread int mod_tbss1;
+__thread int mod_tbss2 __attribute__ ((aligned (0x10)));
+__thread int mod_tbss3 __attribute__ ((aligned (0x1000)));
diff --git a/REORG.TODO/elf/tst-tlsalign-static.c b/REORG.TODO/elf/tst-tlsalign-static.c
new file mode 100644
index 0000000000..1671abf28e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign-static.c
@@ -0,0 +1,2 @@
+#define NO_LIB
+#include "tst-tlsalign.c"
diff --git a/REORG.TODO/elf/tst-tlsalign-vars.c b/REORG.TODO/elf/tst-tlsalign-vars.c
new file mode 100644
index 0000000000..01b3501d3b
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign-vars.c
@@ -0,0 +1,28 @@
+/* This is for tst-tlsalign-extern.c, which see.  It's essential for the
+   purpose of the test that these definitions be in a separate translation
+   unit from the code using the variables.  */
+
+__thread int tdata1 = 1;
+__thread int tdata2 __attribute__ ((aligned (0x10))) = 2;
+__thread int tdata3 __attribute__ ((aligned (0x1000))) = 4;
+__thread int tbss1;
+__thread int tbss2 __attribute__ ((aligned (0x10)));
+__thread int tbss3 __attribute__ ((aligned (0x1000)));
+
+/* This function is never called.  But its presence in this translation
+   unit makes GCC emit the variables above in the order defined (perhaps
+   because it's the order in which they're used here?) rather than
+   reordering them into descending order of alignment requirement--and so
+   keeps it more similar to the tst-tlsalign-static.c case--just in case
+   that affects the bug (though there is no evidence that it does).  */
+
+void
+unused (void)
+{
+  tdata1 = -1;
+  tdata2 = -2;
+  tdata3 = -3;
+  tbss1 = -4;
+  tbss2 = -5;
+  tbss3 = -6;
+}
diff --git a/REORG.TODO/elf/tst-tlsalign.c b/REORG.TODO/elf/tst-tlsalign.c
new file mode 100644
index 0000000000..b129ebda0e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsalign.c
@@ -0,0 +1,84 @@
+/* Test for large alignment in TLS blocks, BZ#18383.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static __thread int tdata1 = 1;
+static __thread int tdata2 __attribute__ ((aligned (0x10))) = 2;
+static __thread int tdata3 __attribute__ ((aligned (0x1000))) = 4;
+static __thread int tbss1;
+static __thread int tbss2 __attribute__ ((aligned (0x10)));
+static __thread int tbss3 __attribute__ ((aligned (0x1000)));
+
+#ifndef NO_LIB
+extern __thread int mod_tdata1;
+extern __thread int mod_tdata2;
+extern __thread int mod_tdata3;
+extern __thread int mod_tbss1;
+extern __thread int mod_tbss2;
+extern __thread int mod_tbss3;
+#endif
+
+static int
+test_one (const char *which, unsigned int alignment, int *var, int value)
+{
+  uintptr_t addr = (uintptr_t) var;
+  unsigned int misalign = addr & (alignment - 1);
+
+  printf ("%s TLS address %p %% %u = %u\n",
+          which, (void *) var, alignment, misalign);
+
+  int got = *var;
+  if (got != value)
+    {
+      printf ("%s value %d should be %d\n", which, got, value);
+      return 1;
+    }
+
+  return misalign != 0;
+}
+
+static int
+do_test (void)
+{
+  int fail = 0;
+
+  fail |= test_one ("tdata1", 4, &tdata1, 1);
+  fail |= test_one ("tdata2", 0x10, &tdata2, 2);
+  fail |= test_one ("tdata3", 0x1000, &tdata3, 4);
+
+  fail |= test_one ("tbss1", 4, &tbss1, 0);
+  fail |= test_one ("tbss2", 0x10, &tbss2, 0);
+  fail |= test_one ("tbss3", 0x1000, &tbss3, 0);
+
+#ifndef NO_LIB
+  fail |= test_one ("mod_tdata1", 4, &mod_tdata1, 1);
+  fail |= test_one ("mod_tdata2", 0x10, &mod_tdata2, 2);
+  fail |= test_one ("mod_tdata3", 0x1000, &mod_tdata3, 4);
+
+  fail |= test_one ("mod_tbss1", 4, &mod_tbss1, 0);
+  fail |= test_one ("mod_tbss2", 0x10, &mod_tbss2, 0);
+  fail |= test_one ("mod_tbss3", 0x1000, &mod_tbss3, 0);
+#endif
+
+  return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-tlsmod1.c b/REORG.TODO/elf/tst-tlsmod1.c
new file mode 100644
index 0000000000..8d9156791b
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod1.c
@@ -0,0 +1,62 @@
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+/* One define int variable, two externs.  */
+COMMON_INT_DEF(foo);
+VAR_INT_DEF(bar);
+VAR_INT_DECL(baz);
+
+extern int in_dso (void);
+
+int
+in_dso (void)
+{
+  int result = 0;
+  int *ap, *bp, *cp;
+
+  /* Get variables using initial exec model.  */
+  fputs ("get sum of foo and bar (IE)", stdout);
+  asm ("" ::: "memory");
+  ap = TLS_IE (foo);
+  bp = TLS_IE (bar);
+  printf (" = %d\n", *ap + *bp);
+  result |= *ap + *bp != 3;
+  if (*ap != 1)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 2)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+
+
+  /* Get variables using generic dynamic model.  */
+  fputs ("get sum of foo and bar and baz (GD)", stdout);
+  ap = TLS_GD (foo);
+  bp = TLS_GD (bar);
+  cp = TLS_GD (baz);
+  printf (" = %d\n", *ap + *bp + *cp);
+  result |= *ap + *bp + *cp != 6;
+  if (*ap != 1)
+    {
+      printf ("foo = %d\n", *ap);
+      result = 1;
+    }
+  if (*bp != 2)
+    {
+      printf ("bar = %d\n", *bp);
+      result = 1;
+    }
+  if (*cp != 3)
+    {
+      printf ("baz = %d\n", *cp);
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod10.c b/REORG.TODO/elf/tst-tlsmod10.c
new file mode 100644
index 0000000000..32e54f3c04
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod10.c
@@ -0,0 +1 @@
+#include "tst-tlsmod8.c"
diff --git a/REORG.TODO/elf/tst-tlsmod11.c b/REORG.TODO/elf/tst-tlsmod11.c
new file mode 100644
index 0000000000..cffbd68edc
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod11.c
@@ -0,0 +1,4 @@
+#include "tst-tls10.h"
+
+__thread struct A a1 = { 4, 5, 6 };
+__thread struct A a2 = { 7, 8, 9 };
diff --git a/REORG.TODO/elf/tst-tlsmod12.c b/REORG.TODO/elf/tst-tlsmod12.c
new file mode 100644
index 0000000000..d0be51891a
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod12.c
@@ -0,0 +1,12 @@
+#include "tst-tls10.h"
+
+extern __thread struct A a2 __attribute__((tls_model("initial-exec")));
+
+void
+check1 (void)
+{
+  if (a1.a != 4 || a1.b != 5 || a1.c != 6)
+    abort ();
+  if (a2.a != 7 || a2.b != 8 || a2.c != 9)
+    abort ();
+}
diff --git a/REORG.TODO/elf/tst-tlsmod13.c b/REORG.TODO/elf/tst-tlsmod13.c
new file mode 100644
index 0000000000..7712d8b8c8
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod13.c
@@ -0,0 +1,7 @@
+__thread int a[2] __attribute__ ((tls_model ("initial-exec")));
+
+int
+foo (void)
+{
+  return a[0];
+}
diff --git a/REORG.TODO/elf/tst-tlsmod13a.c b/REORG.TODO/elf/tst-tlsmod13a.c
new file mode 100644
index 0000000000..ca4eaccbff
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod13a.c
@@ -0,0 +1,9 @@
+__thread int b[2] __attribute__ ((tls_model ("initial-exec")));
+
+extern int foo (void);
+
+int
+bar (void)
+{
+  return foo () + b[0];
+}
diff --git a/REORG.TODO/elf/tst-tlsmod14a.c b/REORG.TODO/elf/tst-tlsmod14a.c
new file mode 100644
index 0000000000..824c06d1f9
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod14a.c
@@ -0,0 +1,35 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#define AL 4096
+struct foo
+{
+  int i;
+} __attribute ((aligned (AL)));
+
+static __thread struct foo f;
+static struct foo g;
+
+
+#ifndef FCT
+# define FCT in_dso1
+#endif
+
+
+int
+FCT (void)
+{
+  puts (__func__);
+
+  int result = 0;
+
+  int fail = (((uintptr_t) &f) & (AL - 1)) != 0;
+  printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK");
+  result |= fail;
+
+  fail = (((uintptr_t) &g) & (AL - 1)) != 0;
+  printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK");
+  result |= fail;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod14b.c b/REORG.TODO/elf/tst-tlsmod14b.c
new file mode 100644
index 0000000000..24d9ceaf7e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod14b.c
@@ -0,0 +1,2 @@
+#define FCT in_dso2
+#include "tst-tlsmod14a.c"
diff --git a/REORG.TODO/elf/tst-tlsmod15a.c b/REORG.TODO/elf/tst-tlsmod15a.c
new file mode 100644
index 0000000000..66c707129a
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod15a.c
@@ -0,0 +1,6 @@
+extern int nonexistent_dummy_var;
+int *
+foo (void)
+{
+  return &nonexistent_dummy_var;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod15b.c b/REORG.TODO/elf/tst-tlsmod15b.c
new file mode 100644
index 0000000000..b37283686a
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod15b.c
@@ -0,0 +1,9 @@
+#include "tst-tls10.h"
+
+__thread int mod15b_var __attribute__((tls_model("initial-exec")));
+
+int
+in_dso (void)
+{
+  return mod15b_var;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod16a.c b/REORG.TODO/elf/tst-tlsmod16a.c
new file mode 100644
index 0000000000..4ec6a6c37d
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod16a.c
@@ -0,0 +1 @@
+int __thread tlsvar;
diff --git a/REORG.TODO/elf/tst-tlsmod16b.c b/REORG.TODO/elf/tst-tlsmod16b.c
new file mode 100644
index 0000000000..1ecba26dbe
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod16b.c
@@ -0,0 +1,7 @@
+extern __thread int tlsvar __attribute__((tls_model("initial-exec")));
+
+void *
+in_dso (void)
+{
+  return &tlsvar;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod17a.c b/REORG.TODO/elf/tst-tlsmod17a.c
new file mode 100644
index 0000000000..24c84a1590
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod17a.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+#ifndef N
+#define N 0
+#endif
+#define CONCAT1(s, n) s##n
+#define CONCAT(s, n) CONCAT1(s, n)
+
+__thread int CONCAT (v, N) = 4;
+
+int
+CONCAT (tlsmod17a, N) (void)
+{
+  int *p = &CONCAT (v, N);
+  /* GCC assumes &var is never NULL, add optimization barrier.  */
+  asm volatile ("" : "+r" (p));
+  if (p == NULL || *p != 4)
+    {
+      printf ("fail %d %p\n", N, p);
+      return 1;
+    }
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod17b.c b/REORG.TODO/elf/tst-tlsmod17b.c
new file mode 100644
index 0000000000..6178828737
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod17b.c
@@ -0,0 +1,15 @@
+#define P(N) extern int tlsmod17a##N (void);
+#define PS P(0) P(1) P(2) P(3) P(4) P(5) P(6) P(7) P(8) P(9) \
+	   P(10) P(12) P(13) P(14) P(15) P(16) P(17) P(18) P(19)
+PS
+#undef P
+
+int
+tlsmod17b (void)
+{
+  int res = 0;
+#define P(N) res |= tlsmod17a##N ();
+  PS
+#undef P
+  return res;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod18a.c b/REORG.TODO/elf/tst-tlsmod18a.c
new file mode 100644
index 0000000000..1d728daa05
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod18a.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+#ifndef N
+# define N 0
+#endif
+
+static __thread int var = 4;
+
+int
+test (void)
+{
+  int *p = &var;
+  /* GCC assumes &var is never NULL, add optimization barrier.  */
+  asm volatile ("" : "+r" (p));
+  if (p == NULL || *p != 4)
+    {
+      printf ("fail %d %p\n", N, p);
+      return 1;
+    }
+  return 0;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod2.c b/REORG.TODO/elf/tst-tlsmod2.c
new file mode 100644
index 0000000000..40eb1407f8
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod2.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+COMMON_INT_DEF(foo);
+
+
+int
+in_dso (int n, int *caller_foop)
+{
+  int *foop;
+  int result = 0;
+
+  puts ("foo");			/* Make sure PLT is used before macros.  */
+  asm ("" ::: "memory");
+
+  foop = TLS_GD (foo);
+
+  if (caller_foop != NULL && foop != caller_foop)
+    {
+      printf ("callers address of foo differs: %p vs %p\n", caller_foop, foop);
+      result = 1;
+    }
+  else if (*foop != n)
+    {
+      printf ("foo != %d\n", n);
+      result = 1;
+    }
+
+  *foop = 16;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod3.c b/REORG.TODO/elf/tst-tlsmod3.c
new file mode 100644
index 0000000000..6d186c47ee
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod3.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+extern int in_dso (int n, int *caller_foop);
+
+COMMON_INT_DEF(comm_n);
+
+
+
+
+int
+in_dso2 (void)
+{
+  int *foop;
+  int result = 0;
+  static int n;
+  int *np;
+
+  puts ("foo");			/* Make sure PLT is used before macros.  */
+  asm ("" ::: "memory");
+
+  foop = TLS_GD (foo);
+  np = TLS_GD (comm_n);
+
+  if (n != *np)
+    {
+      printf ("n = %d != comm_n = %d\n", n, *np);
+      result = 1;
+    }
+
+  result |= in_dso (*foop = 42 + n++, foop);
+
+  *foop = 16;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod4.c b/REORG.TODO/elf/tst-tlsmod4.c
new file mode 100644
index 0000000000..86889aac7e
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod4.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+#include "tls-macros.h"
+
+
+COMMON_INT_DEF(baz);
+
+
+int
+in_dso (int n, int *caller_bazp)
+{
+  int *bazp;
+  int result = 0;
+
+  puts ("foo");			/* Make sure PLT is used before macros.  */
+  asm ("" ::: "memory");
+
+  bazp = TLS_GD (baz);
+
+  if (caller_bazp != NULL && bazp != caller_bazp)
+    {
+      printf ("callers address of baz differs: %p vs %p\n", caller_bazp, bazp);
+      result = 1;
+    }
+  else if (*bazp != n)
+    {
+      printf ("baz != %d\n", n);
+      result = 1;
+    }
+
+  *bazp = 16;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod5.c b/REORG.TODO/elf/tst-tlsmod5.c
new file mode 100644
index 0000000000..a97c7e5e0c
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod5.c
@@ -0,0 +1,3 @@
+#include "tls-macros.h"
+
+COMMON_INT_DEF(foo);
diff --git a/REORG.TODO/elf/tst-tlsmod6.c b/REORG.TODO/elf/tst-tlsmod6.c
new file mode 100644
index 0000000000..e968596dd4
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod6.c
@@ -0,0 +1,3 @@
+#include "tls-macros.h"
+
+COMMON_INT_DEF(bar);
diff --git a/REORG.TODO/elf/tst-tlsmod7.c b/REORG.TODO/elf/tst-tlsmod7.c
new file mode 100644
index 0000000000..3df7907bcf
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod7.c
@@ -0,0 +1,101 @@
+#include "tst-tls10.h"
+
+__thread int dummy __attribute__((visibility ("hidden"))) = 12;
+__thread struct A a1 = { 4, 5, 6 };
+__thread struct A a2 = { 7, 8, 9 };
+__thread struct A a3 __attribute__((tls_model("initial-exec")))
+  = { 10, 11, 12 };
+__thread struct A a4 __attribute__((tls_model("initial-exec")))
+  = { 13, 14, 15 };
+static __thread struct A local1 = { 16, 17, 18 };
+static __thread struct A local2 __attribute__((tls_model("initial-exec")))
+  = { 19, 20, 21 };
+
+void
+check1 (void)
+{
+  if (a1.a != 4 || a1.b != 5 || a1.c != 6)
+    abort ();
+  if (a2.a != 22 || a2.b != 23 || a2.c != 24)
+    abort ();
+  if (a3.a != 10 || a3.b != 11 || a3.c != 12)
+    abort ();
+  if (a4.a != 25 || a4.b != 26 || a4.c != 27)
+    abort ();
+  if (local1.a != 16 || local1.b != 17 || local1.c != 18)
+    abort ();
+  if (local2.a != 19 || local2.b != 20 || local2.c != 21)
+    abort ();
+}
+
+struct A *
+f1a (void)
+{
+  return &a1;
+}
+
+struct A *
+f2a (void)
+{
+  return &a2;
+}
+
+struct A *
+f3a (void)
+{
+  return &a3;
+}
+
+struct A *
+f4a (void)
+{
+  return &a4;
+}
+
+struct A *
+f5a (void)
+{
+  return &local1;
+}
+
+struct A *
+f6a (void)
+{
+  return &local2;
+}
+
+int
+f1b (void)
+{
+  return a1.a;
+}
+
+int
+f2b (void)
+{
+  return a2.b;
+}
+
+int
+f3b (void)
+{
+  return a3.c;
+}
+
+int
+f4b (void)
+{
+  return a4.a;
+}
+
+int
+f5b (void)
+{
+  return local1.b;
+}
+
+int
+f6b (void)
+{
+  return local2.c;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod8.c b/REORG.TODO/elf/tst-tlsmod8.c
new file mode 100644
index 0000000000..89772ac42f
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod8.c
@@ -0,0 +1,70 @@
+#include "tst-tls10.h"
+
+__thread long long dummy __attribute__((visibility ("hidden"))) = 12;
+__thread struct A a2 = { 22, 23, 24 };
+__thread struct A a4 __attribute__((tls_model("initial-exec")))
+  = { 25, 26, 27 };
+static __thread struct A local1 = { 28, 29, 30 };
+static __thread struct A local2 __attribute__((tls_model("initial-exec")))
+  = { 31, 32, 33 };
+
+void
+check2 (void)
+{
+  if (a2.a != 22 || a2.b != 23 || a2.c != 24)
+    abort ();
+  if (a4.a != 25 || a4.b != 26 || a4.c != 27)
+    abort ();
+  if (local1.a != 28 || local1.b != 29 || local1.c != 30)
+    abort ();
+  if (local2.a != 31 || local2.b != 32 || local2.c != 33)
+    abort ();
+}
+
+struct A *
+f7a (void)
+{
+  return &a2;
+}
+
+struct A *
+f8a (void)
+{
+  return &a4;
+}
+
+struct A *
+f9a (void)
+{
+  return &local1;
+}
+
+struct A *
+f10a (void)
+{
+  return &local2;
+}
+
+int
+f7b (void)
+{
+  return a2.b;
+}
+
+int
+f8b (void)
+{
+  return a4.a;
+}
+
+int
+f9b (void)
+{
+  return local1.b;
+}
+
+int
+f10b (void)
+{
+  return local2.c;
+}
diff --git a/REORG.TODO/elf/tst-tlsmod9.c b/REORG.TODO/elf/tst-tlsmod9.c
new file mode 100644
index 0000000000..6b11ed58b8
--- /dev/null
+++ b/REORG.TODO/elf/tst-tlsmod9.c
@@ -0,0 +1,99 @@
+#include "tst-tls10.h"
+
+__thread int dummy __attribute__((visibility ("hidden"))) = 12;
+__thread struct A a1 = { 4, 5, 6 };
+__thread struct A a3 __attribute__((tls_model("initial-exec")))
+  = { 10, 11, 12 };
+extern __thread struct A a4 __attribute__((tls_model("initial-exec")));
+static __thread struct A local1 = { 16, 17, 18 };
+static __thread struct A local2 __attribute__((tls_model("initial-exec")))
+  = { 19, 20, 21 };
+
+void
+check1 (void)
+{
+  if (a1.a != 4 || a1.b != 5 || a1.c != 6)
+    abort ();
+  if (a2.a != 22 || a2.b != 23 || a2.c != 24)
+    abort ();
+  if (a3.a != 10 || a3.b != 11 || a3.c != 12)
+    abort ();
+  if (a4.a != 25 || a4.b != 26 || a4.c != 27)
+    abort ();
+  if (local1.a != 16 || local1.b != 17 || local1.c != 18)
+    abort ();
+  if (local2.a != 19 || local2.b != 20 || local2.c != 21)
+    abort ();
+}
+
+struct A *
+f1a (void)
+{
+  return &a1;
+}
+
+struct A *
+f2a (void)
+{
+  return &a2;
+}
+
+struct A *
+f3a (void)
+{
+  return &a3;
+}
+
+struct A *
+f4a (void)
+{
+  return &a4;
+}
+
+struct A *
+f5a (void)
+{
+  return &local1;
+}
+
+struct A *
+f6a (void)
+{
+  return &local2;
+}
+
+int
+f1b (void)
+{
+  return a1.a;
+}
+
+int
+f2b (void)
+{
+  return a2.b;
+}
+
+int
+f3b (void)
+{
+  return a3.c;
+}
+
+int
+f4b (void)
+{
+  return a4.a;
+}
+
+int
+f5b (void)
+{
+  return local1.b;
+}
+
+int
+f6b (void)
+{
+  return local2.c;
+}
diff --git a/REORG.TODO/elf/tst-unique1.c b/REORG.TODO/elf/tst-unique1.c
new file mode 100644
index 0000000000..b5e53e49a0
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique1.c
@@ -0,0 +1,73 @@
+#include <config.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <sys/mman.h>
+
+static int
+do_test (void)
+{
+  void *h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      puts ("cannot load tst-unique1mod1");
+      return 1;
+    }
+  int *(*f1) (void) = dlsym (h1, "f");
+  if (f1 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod1");
+      return 1;
+    }
+  void *h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("cannot load tst-unique1mod2");
+      return 1;
+    }
+  int (*f2) (int *) = dlsym (h2, "f");
+  if (f2 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod2");
+      return 1;
+    }
+  if (f2 (f1 ()))
+    {
+      puts ("f from tst-unique1mod2 failed");
+      return 1;
+    }
+  dlclose (h2);
+  dlclose (h1);
+  mmap (NULL, 1024 * 1024 * 16, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("cannot load tst-unique1mod2");
+      return 1;
+    }
+  f2 = dlsym (h2, "f");
+  if (f2 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod2");
+      return 1;
+    }
+  h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      puts ("cannot load tst-unique1mod1");
+      return 1;
+    }
+  f1 = dlsym (h1, "f");
+  if (f1 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod1");
+      return 1;
+    }
+  if (f2 (f1 ()))
+    {
+      puts ("f from tst-unique1mod2 failed");
+      return 1;
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-unique1mod1.c b/REORG.TODO/elf/tst-unique1mod1.c
new file mode 100644
index 0000000000..84b1f908d6
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique1mod1.c
@@ -0,0 +1,16 @@
+#include <config.h>
+
+asm (".data;"
+     ".globl var\n"
+     ".type var, %gnu_unique_object\n"
+     ".size var, 4\n"
+     "var:.zero 4\n"
+     ".previous");
+extern int var;
+
+int *
+f (void)
+{
+  var = 1;
+  return &var;
+}
diff --git a/REORG.TODO/elf/tst-unique1mod2.c b/REORG.TODO/elf/tst-unique1mod2.c
new file mode 100644
index 0000000000..126ca1ac6c
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique1mod2.c
@@ -0,0 +1,15 @@
+#include <config.h>
+
+asm (".data;"
+     ".globl var\n"
+     ".type var, %gnu_unique_object\n"
+     ".size var, 4\n"
+     "var:.zero 4\n"
+     ".previous");
+extern int var;
+
+int
+f (int *p)
+{
+  return &var != p || *p != 1;
+}
diff --git a/REORG.TODO/elf/tst-unique2.c b/REORG.TODO/elf/tst-unique2.c
new file mode 100644
index 0000000000..e0173b7bcc
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique2.c
@@ -0,0 +1,27 @@
+#include <config.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+extern int var;
+
+static int
+do_test (void)
+{
+  var = 1;
+
+  void *h = dlopen ("tst-unique2mod2.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("cannot load tst-unique2mod2");
+      return 1;
+    }
+  int (*f) (int *) = dlsym (h, "f");
+  if (f == NULL)
+    {
+      puts ("cannot locate f in tst-unique2mod2");
+      return 1;
+    }
+  return f (&var);
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/elf/tst-unique2mod1.c b/REORG.TODO/elf/tst-unique2mod1.c
new file mode 100644
index 0000000000..7cdb0eb0a0
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique2mod1.c
@@ -0,0 +1,8 @@
+#include <config.h>
+
+asm (".data;"
+     ".globl var\n"
+     ".type var, %gnu_unique_object\n"
+     ".size var, 4\n"
+     "var:.zero 4\n"
+     ".previous");
diff --git a/REORG.TODO/elf/tst-unique2mod2.c b/REORG.TODO/elf/tst-unique2mod2.c
new file mode 100644
index 0000000000..126ca1ac6c
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique2mod2.c
@@ -0,0 +1,15 @@
+#include <config.h>
+
+asm (".data;"
+     ".globl var\n"
+     ".type var, %gnu_unique_object\n"
+     ".size var, 4\n"
+     "var:.zero 4\n"
+     ".previous");
+extern int var;
+
+int
+f (int *p)
+{
+  return &var != p || *p != 1;
+}
diff --git a/REORG.TODO/elf/tst-unique3.cc b/REORG.TODO/elf/tst-unique3.cc
new file mode 100644
index 0000000000..efdd6d78c2
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique3.cc
@@ -0,0 +1,24 @@
+#include "tst-unique3.h"
+
+#include <cstdio>
+#include "../dlfcn/dlfcn.h"
+
+int t = S<char>::i;
+
+int
+main (void)
+{
+  std::printf ("%d %d\n", S<char>::i, t);
+  int result = S<char>::i++ != 1 || t != 1;
+  result |= in_lib ();
+  void *d = dlopen ("$ORIGIN/tst-unique3lib2.so", RTLD_LAZY);
+  int (*fp) ();
+  if (d == NULL || (fp = (int(*)()) dlsym (d, "in_lib2")) == NULL)
+    {
+      std::printf ("failed to get symbol in_lib2\n");
+      return 1;
+    }
+  result |= fp ();
+  dlclose (d);
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-unique3.h b/REORG.TODO/elf/tst-unique3.h
new file mode 100644
index 0000000000..716d23641c
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique3.h
@@ -0,0 +1,8 @@
+// BZ 12510
+template<typename T>
+struct S
+{
+  static int i;
+};
+
+extern int in_lib (void);
diff --git a/REORG.TODO/elf/tst-unique3lib.cc b/REORG.TODO/elf/tst-unique3lib.cc
new file mode 100644
index 0000000000..fa8e85a36c
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique3lib.cc
@@ -0,0 +1,11 @@
+#include <cstdio>
+#include "tst-unique3.h"
+template<typename T> int S<T>::i = 1;
+static int i = S<char>::i;
+
+int
+in_lib (void)
+{
+  std::printf ("in_lib: %d %d\n", S<char>::i, i);
+  return S<char>::i++ != 2 || i != 1;
+}
diff --git a/REORG.TODO/elf/tst-unique3lib2.cc b/REORG.TODO/elf/tst-unique3lib2.cc
new file mode 100644
index 0000000000..17d817e12e
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique3lib2.cc
@@ -0,0 +1,12 @@
+#include <cstdio>
+#include "tst-unique3.h"
+
+template<typename T> int S<T>::i;
+
+extern "C"
+int
+in_lib2 ()
+{
+  std::printf ("in_lib2: %d\n", S<char>::i);
+  return S<char>::i != 3;
+}
diff --git a/REORG.TODO/elf/tst-unique4.cc b/REORG.TODO/elf/tst-unique4.cc
new file mode 100644
index 0000000000..575c70d3a1
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique4.cc
@@ -0,0 +1,28 @@
+// BZ 12511
+#include "tst-unique4.h"
+
+#include <cstdio>
+
+static int a[24] =
+  {
+    S<1>::i, S<2>::i, S<3>::i, S<4>::i, S<5>::i, S<6>::i, S<7>::i, S<8>::i,
+    S<9>::i, S<10>::i, S<11>::i, S<12>::i, S<13>::i, S<14>::i, S<15>::i,
+    S<16>::i, S<17>::i, S<18>::i, S<19>::i, S<20>::i, S<21>::i, S<22>::i,
+    S<23>::i, S<24>::i
+  };
+
+int
+main (void)
+{
+  int result = 0;
+  for (int i = 0; i < 24; ++i)
+    {
+      printf("%d ", a[i]);
+      result |= a[i] != i + 1;
+    }
+
+  printf("\n%d\n", S<1>::j);
+  result |= S<1>::j != -1;
+
+  return result;
+}
diff --git a/REORG.TODO/elf/tst-unique4.h b/REORG.TODO/elf/tst-unique4.h
new file mode 100644
index 0000000000..2d377f5d51
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique4.h
@@ -0,0 +1,7 @@
+// BZ 12511
+template<int N>
+struct S
+{
+  static int i;
+  static const int j;
+};
diff --git a/REORG.TODO/elf/tst-unique4lib.cc b/REORG.TODO/elf/tst-unique4lib.cc
new file mode 100644
index 0000000000..17a7cdf567
--- /dev/null
+++ b/REORG.TODO/elf/tst-unique4lib.cc
@@ -0,0 +1,17 @@
+// BZ 12511
+#include "tst-unique4.h"
+
+template<int N>
+int S<N>::i = N;
+template<int N>
+const int S<N>::j __attribute__ ((used)) = -1;
+
+static int a[24] __attribute__ ((used)) =
+  {
+    S<1>::i, S<2>::i, S<3>::i, S<4>::i, S<5>::i, S<6>::i, S<7>::i, S<8>::i,
+    S<9>::i, S<10>::i, S<11>::i, S<12>::i, S<13>::i, S<14>::i, S<15>::i,
+    S<16>::i, S<17>::i, S<18>::i, S<19>::i, S<20>::i, S<21>::i, S<22>::i,
+    S<23>::i, S<24>::i
+  };
+
+static int b __attribute__ ((used)) = S<1>::j;
diff --git a/REORG.TODO/elf/unload.c b/REORG.TODO/elf/unload.c
new file mode 100644
index 0000000000..4566f226f8
--- /dev/null
+++ b/REORG.TODO/elf/unload.c
@@ -0,0 +1,91 @@
+/* Test for unloading (really unmapping) of objects.  By Franz Sirl.
+   This test does not have to passed in all dlopen() et.al. implementation
+   since it is not required the unloading actually happens.  But we
+   require it for glibc.  */
+
+#include <dlfcn.h>
+#include <link.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+#define OUT \
+  for (map = MAPS; map != NULL; map = map->l_next)			      \
+    if (map->l_type == lt_loaded)					      \
+      printf ("name = \"%s\", direct_opencount = %d\n",			      \
+	      map->l_name, (int) map->l_direct_opencount);		      \
+  fflush (stdout)
+
+typedef struct
+{
+  void *next;
+} strct;
+
+int
+main (void)
+{
+   void *sohandle;
+   strct *testdat;
+   int ret;
+   int result = 0;
+   struct link_map *map;
+
+   mtrace ();
+
+   puts ("\nBefore");
+   OUT;
+
+   sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL);
+   if (sohandle == NULL)
+     {
+       printf ("*** first dlopen failed: %s\n", dlerror ());
+       exit (1);
+     }
+
+   puts ("\nAfter loading unloadmod.so");
+   OUT;
+
+   testdat = dlsym (sohandle, "testdat");
+   testdat->next = (void *) -1;
+
+   ret = dlclose (sohandle);
+   if (ret != 0)
+     {
+       puts ("*** first dlclose failed");
+       result = 1;
+     }
+
+   puts ("\nAfter closing unloadmod.so");
+   OUT;
+
+   sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL);
+   if (sohandle == NULL)
+     {
+       printf ("*** second dlopen failed: %s\n", dlerror ());
+       exit (1);
+     }
+
+   puts ("\nAfter loading unloadmod.so the second time");
+   OUT;
+
+   testdat = dlsym (sohandle, "testdat");
+   if (testdat->next == (void *) -1)
+     {
+       puts ("*** testdat->next == (void *) -1");
+       result = 1;
+     }
+
+   ret = dlclose (sohandle);
+   if (ret != 0)
+     {
+       puts ("*** second dlclose failed");
+       result = 1;
+     }
+
+   puts ("\nAfter closing unloadmod.so again");
+   OUT;
+
+   return result;
+}
diff --git a/REORG.TODO/elf/unload2.c b/REORG.TODO/elf/unload2.c
new file mode 100644
index 0000000000..eef2bfd426
--- /dev/null
+++ b/REORG.TODO/elf/unload2.c
@@ -0,0 +1,59 @@
+#include <dlfcn.h>
+#include <elf.h>
+#include <errno.h>
+#include <error.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAPS ((struct link_map *) _r_debug.r_map)
+
+#define OUT \
+  for (map = MAPS; map != NULL; map = map->l_next)			      \
+    if (map->l_type == lt_loaded)					      \
+      printf ("name = \"%s\", direct_opencount = %d\n",			      \
+	      map->l_name, (int) map->l_direct_opencount);		      \
+  fflush (stdout)
+
+int
+main (void)
+{
+  void *h[3];
+  struct link_map *map;
+  void (*fp) (void);
+
+  h[0] = dlopen ("unload2mod.so", RTLD_LAZY);
+  h[1] = dlopen ("unload2mod.so", RTLD_LAZY);
+  if (h[0] == NULL || h[1] == NULL)
+    error (EXIT_FAILURE, errno, "cannot load \"unload2mod.so\"");
+  h[2] = dlopen ("unload2dep.so", RTLD_LAZY);
+  if (h[2] == NULL)
+    error (EXIT_FAILURE, errno, "cannot load \"unload2dep.so\"");
+
+  puts ("\nAfter loading everything:");
+  OUT;
+
+  dlclose (h[0]);
+
+  puts ("\nAfter unloading \"unload2mod.so\" once:");
+  OUT;
+
+  dlclose (h[1]);
+
+  puts ("\nAfter unloading \"unload2mod.so\" twice:");
+  OUT;
+
+  fp = dlsym (h[2], "foo");
+  puts ("\nnow calling `foo'");
+  fflush (stdout);
+  fp ();
+  puts ("managed to call `foo'");
+  fflush (stdout);
+
+  dlclose (h[2]);
+
+  puts ("\nAfter unloading \"unload2dep.so\":");
+  OUT;
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload2dep.c b/REORG.TODO/elf/unload2dep.c
new file mode 100644
index 0000000000..0d319515d5
--- /dev/null
+++ b/REORG.TODO/elf/unload2dep.c
@@ -0,0 +1,6 @@
+extern void foo (void);
+
+void
+foo (void)
+{
+}
diff --git a/REORG.TODO/elf/unload2mod.c b/REORG.TODO/elf/unload2mod.c
new file mode 100644
index 0000000000..9c2ea586bc
--- /dev/null
+++ b/REORG.TODO/elf/unload2mod.c
@@ -0,0 +1,8 @@
+extern void foo (void);
+extern void bar (void);
+
+void
+bar (void)
+{
+  foo ();
+}
diff --git a/REORG.TODO/elf/unload3.c b/REORG.TODO/elf/unload3.c
new file mode 100644
index 0000000000..6f1af707e6
--- /dev/null
+++ b/REORG.TODO/elf/unload3.c
@@ -0,0 +1,41 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *g = dlopen ("unload3mod1.so", RTLD_GLOBAL | RTLD_NOW);
+  void *h = dlopen ("unload3mod2.so", RTLD_GLOBAL | RTLD_NOW);
+  if (g == NULL || h == NULL)
+    {
+      printf ("dlopen unload3mod{1,2}.so failed: %p %p\n", g, h);
+      return 1;
+    }
+  dlclose (h);
+  dlclose (g);
+
+  g = dlopen ("unload3mod3.so", RTLD_GLOBAL | RTLD_NOW);
+  h = dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW);
+  if (g == NULL || h == NULL)
+    {
+      printf ("dlopen unload3mod{3,4}.so failed: %p %p\n", g, h);
+      return 1;
+    }
+
+  int (*fn) (int);
+  fn = dlsym (h, "bar");
+  if (fn == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+
+  int val = fn (16);
+  if (val != 24)
+    {
+      printf ("bar returned %d != 24\n", val);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload3mod1.c b/REORG.TODO/elf/unload3mod1.c
new file mode 100644
index 0000000000..e886b11c18
--- /dev/null
+++ b/REORG.TODO/elf/unload3mod1.c
@@ -0,0 +1 @@
+int dummy1;
diff --git a/REORG.TODO/elf/unload3mod2.c b/REORG.TODO/elf/unload3mod2.c
new file mode 100644
index 0000000000..03252a523b
--- /dev/null
+++ b/REORG.TODO/elf/unload3mod2.c
@@ -0,0 +1 @@
+int dummy2;
diff --git a/REORG.TODO/elf/unload3mod3.c b/REORG.TODO/elf/unload3mod3.c
new file mode 100644
index 0000000000..046022c55d
--- /dev/null
+++ b/REORG.TODO/elf/unload3mod3.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+foo (int x)
+{
+  puts ("foo");
+  return x * 2;
+}
diff --git a/REORG.TODO/elf/unload3mod4.c b/REORG.TODO/elf/unload3mod4.c
new file mode 100644
index 0000000000..52f808e79b
--- /dev/null
+++ b/REORG.TODO/elf/unload3mod4.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int foo (int x);
+
+int
+bar (int x)
+{
+  puts ("bar");
+  fflush (stdout);
+  x = foo (x - 4);
+  puts ("bar after foo");
+  return x;
+}
diff --git a/REORG.TODO/elf/unload4.c b/REORG.TODO/elf/unload4.c
new file mode 100644
index 0000000000..6e171a22e0
--- /dev/null
+++ b/REORG.TODO/elf/unload4.c
@@ -0,0 +1,48 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <malloc.h>
+
+int
+main (void)
+{
+#ifdef M_PERTURB
+  mallopt (M_PERTURB, 0xaa);
+#endif
+
+  void *h;
+  int (*fn) (int);
+  h = dlopen ("unload4mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("1st dlopen failed");
+      return 1;
+    }
+  fn = dlsym (h, "foo");
+  if (fn == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+  int n = fn (10);
+  if (n != 28)
+    {
+      printf ("foo (10) returned %d != 28\n", n);
+      return 1;
+    }
+  dlclose (h);
+  h = dlopen ("unload4mod3.so", RTLD_LAZY);
+  fn = dlsym (h, "mod3fn2");
+  if (fn == NULL)
+    {
+      puts ("second dlsym failed");
+      return 1;
+    }
+  n = fn (10);
+  if (n != 22)
+    {
+      printf ("mod3fn2 (10) returned %d != 22\n", n);
+      return 1;
+    }
+  dlclose (h);
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload4mod1.c b/REORG.TODO/elf/unload4mod1.c
new file mode 100644
index 0000000000..38c5b0168d
--- /dev/null
+++ b/REORG.TODO/elf/unload4mod1.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern int bar (int);
+
+int
+foo (int x)
+{
+  puts ("in foo");
+  return bar (x / 2) + 2;
+}
diff --git a/REORG.TODO/elf/unload4mod2.c b/REORG.TODO/elf/unload4mod2.c
new file mode 100644
index 0000000000..497ef5d93b
--- /dev/null
+++ b/REORG.TODO/elf/unload4mod2.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+baz (int x)
+{
+  puts ("in baz");
+  return x * 4;
+}
diff --git a/REORG.TODO/elf/unload4mod3.c b/REORG.TODO/elf/unload4mod3.c
new file mode 100644
index 0000000000..4b280bc05b
--- /dev/null
+++ b/REORG.TODO/elf/unload4mod3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+int
+__attribute__((noinline))
+mod3fn1 (int x)
+{
+  puts ("in mod3fn1");
+  return x + 6;
+}
+
+int
+mod3fn2 (int x)
+{
+  puts ("in mod3fn2");
+  return mod3fn1 (x / 2) * 2;
+}
diff --git a/REORG.TODO/elf/unload4mod4.c b/REORG.TODO/elf/unload4mod4.c
new file mode 100644
index 0000000000..ba5a144d38
--- /dev/null
+++ b/REORG.TODO/elf/unload4mod4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+baz (int x)
+{
+  abort ();
+}
+
+int
+bar (int x)
+{
+  puts ("in bar");
+  return baz (x + 1) + 2;
+}
diff --git a/REORG.TODO/elf/unload5.c b/REORG.TODO/elf/unload5.c
new file mode 100644
index 0000000000..0555052ce8
--- /dev/null
+++ b/REORG.TODO/elf/unload5.c
@@ -0,0 +1,42 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *g = dlopen ("unload3mod1.so", RTLD_GLOBAL | RTLD_NOW);
+  void *h = dlopen ("unload3mod2.so", RTLD_GLOBAL | RTLD_NOW);
+  if (g == NULL || h == NULL)
+    {
+      printf ("dlopen unload3mod{1,2}.so failed: %p %p\n", g, h);
+      return 1;
+    }
+  dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW);
+  dlclose (h);
+  dlclose (g);
+
+  g = dlopen ("unload3mod3.so", RTLD_GLOBAL | RTLD_NOW);
+  h = dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW);
+  if (g == NULL || h == NULL)
+    {
+      printf ("dlopen unload3mod{3,4}.so failed: %p %p\n", g, h);
+      return 1;
+    }
+
+  int (*fn) (int);
+  fn = dlsym (h, "bar");
+  if (fn == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+
+  int val = fn (16);
+  if (val != 24)
+    {
+      printf ("bar returned %d != 24\n", val);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload6.c b/REORG.TODO/elf/unload6.c
new file mode 100644
index 0000000000..1efc7eb841
--- /dev/null
+++ b/REORG.TODO/elf/unload6.c
@@ -0,0 +1,30 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *h = dlopen ("unload6mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload6mod1.so failed");
+      return 1;
+    }
+
+  int (*fn) (int);
+  fn = dlsym (h, "foo");
+  if (fn == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+
+  int val = fn (16);
+  if (val != 24)
+    {
+      printf ("foo returned %d != 24\n", val);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload6mod1.c b/REORG.TODO/elf/unload6mod1.c
new file mode 100644
index 0000000000..24f2e5a19a
--- /dev/null
+++ b/REORG.TODO/elf/unload6mod1.c
@@ -0,0 +1,16 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+foo (int i)
+{
+  void *h = dlopen ("unload6mod2.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload6mod2.so failed");
+      return 1;
+    }
+
+  dlclose (h);
+  return i + 8;
+}
diff --git a/REORG.TODO/elf/unload6mod2.c b/REORG.TODO/elf/unload6mod2.c
new file mode 100644
index 0000000000..980efa4b0e
--- /dev/null
+++ b/REORG.TODO/elf/unload6mod2.c
@@ -0,0 +1,23 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void *h;
+
+static void __attribute__((constructor))
+mod2init (void)
+{
+  h = dlopen ("unload6mod3.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload6mod3.so failed");
+      fflush (stdout);
+      _exit (1);
+    }
+}
+
+static void __attribute__((destructor))
+mod2fini (void)
+{
+  dlclose (h);
+}
diff --git a/REORG.TODO/elf/unload6mod3.c b/REORG.TODO/elf/unload6mod3.c
new file mode 100644
index 0000000000..7b29e1d626
--- /dev/null
+++ b/REORG.TODO/elf/unload6mod3.c
@@ -0,0 +1,23 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void *h;
+
+static void __attribute__((constructor))
+mod3init (void)
+{
+  h = dlopen ("unload6mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload6mod1.so failed");
+      fflush (stdout);
+      _exit (1);
+    }
+}
+
+static void __attribute__((destructor))
+mod3fini (void)
+{
+  dlclose (h);
+}
diff --git a/REORG.TODO/elf/unload7.c b/REORG.TODO/elf/unload7.c
new file mode 100644
index 0000000000..198f7db286
--- /dev/null
+++ b/REORG.TODO/elf/unload7.c
@@ -0,0 +1,39 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *h = dlopen ("$ORIGIN/unload7mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload7mod1.so failed");
+      return 1;
+    }
+
+  int (*fn) (void);
+  fn = dlsym (h, "foo");
+  if (fn == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+
+  int ret = 0;
+  if (fn () == 0)
+    ++ret;
+
+  void *h2 = dlopen ("$ORIGIN/unload7mod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("dlopen unload7mod2.so failed");
+      return 1;
+    }
+  dlclose (h2);
+
+  if (fn () == 0)
+    ++ret;
+
+  dlclose (h);
+  return ret;
+}
diff --git a/REORG.TODO/elf/unload7mod1.c b/REORG.TODO/elf/unload7mod1.c
new file mode 100644
index 0000000000..7435adce2c
--- /dev/null
+++ b/REORG.TODO/elf/unload7mod1.c
@@ -0,0 +1,11 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+foo (int i)
+{
+  if (dlsym (RTLD_DEFAULT, "unload7_nonexistent_symbol") == NULL)
+    return 1;
+  puts ("dlsym returned non-NULL");
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload7mod2.c b/REORG.TODO/elf/unload7mod2.c
new file mode 100644
index 0000000000..6d1a0d47b7
--- /dev/null
+++ b/REORG.TODO/elf/unload7mod2.c
@@ -0,0 +1 @@
+int x;
diff --git a/REORG.TODO/elf/unload8.c b/REORG.TODO/elf/unload8.c
new file mode 100644
index 0000000000..f984a38098
--- /dev/null
+++ b/REORG.TODO/elf/unload8.c
@@ -0,0 +1,33 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  void *h = dlopen ("$ORIGIN/unload8mod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload8mod1.so failed");
+      return 1;
+    }
+
+  void *h2 = dlopen ("$ORIGIN/unload8mod1x.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("dlopen unload8mod1x.so failed");
+      return 1;
+    }
+  dlclose (h2);
+
+  int (*mod1) (void) = dlsym (h, "mod1");
+  if (mod1 == NULL)
+    {
+      puts ("dlsym failed");
+      return 1;
+    }
+
+  mod1 ();
+  dlclose (h);
+
+  return 0;
+}
diff --git a/REORG.TODO/elf/unload8mod1.c b/REORG.TODO/elf/unload8mod1.c
new file mode 100644
index 0000000000..fe7e81c1c3
--- /dev/null
+++ b/REORG.TODO/elf/unload8mod1.c
@@ -0,0 +1,7 @@
+extern void mod2 (void);
+
+void
+mod1 (void)
+{
+  mod2 ();
+}
diff --git a/REORG.TODO/elf/unload8mod1x.c b/REORG.TODO/elf/unload8mod1x.c
new file mode 100644
index 0000000000..835b634914
--- /dev/null
+++ b/REORG.TODO/elf/unload8mod1x.c
@@ -0,0 +1 @@
+int mod1x;
diff --git a/REORG.TODO/elf/unload8mod2.c b/REORG.TODO/elf/unload8mod2.c
new file mode 100644
index 0000000000..2fd8b6768a
--- /dev/null
+++ b/REORG.TODO/elf/unload8mod2.c
@@ -0,0 +1,7 @@
+extern void mod3 (void);
+
+void
+mod2 (void)
+{
+  mod3 ();
+}
diff --git a/REORG.TODO/elf/unload8mod3.c b/REORG.TODO/elf/unload8mod3.c
new file mode 100644
index 0000000000..d49e22b24c
--- /dev/null
+++ b/REORG.TODO/elf/unload8mod3.c
@@ -0,0 +1,27 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+mod3_fini2 (void)
+{
+}
+
+void
+mod3_fini (void)
+{
+  mod3_fini2 ();
+}
+
+void
+mod3 (void)
+{
+  void *h = dlopen ("$ORIGIN/unload8mod2.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen unload8mod2.so failed");
+      exit (1);
+    }
+
+  atexit (mod3_fini);
+}
diff --git a/REORG.TODO/elf/unloadmod.c b/REORG.TODO/elf/unloadmod.c
new file mode 100644
index 0000000000..3aa5403edf
--- /dev/null
+++ b/REORG.TODO/elf/unloadmod.c
@@ -0,0 +1,4 @@
+struct testdat
+{
+  void *next;
+} testdat;
diff --git a/REORG.TODO/elf/vismain.c b/REORG.TODO/elf/vismain.c
new file mode 100644
index 0000000000..43f1d8f095
--- /dev/null
+++ b/REORG.TODO/elf/vismain.c
@@ -0,0 +1,260 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file must be compiled as PIE to avoid copy relocation when
+   accessing protected symbols defined in shared libaries since copy
+   relocation doesn't work with protected symbols and linker in
+   binutils 2.26 enforces this rule.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vismod.h"
+
+/* Prototype for our test function.  */
+extern int do_test (void);
+
+
+/* This defines the `main' function and some more.  */
+#include <support/test-driver.c>
+
+
+/* Prototypes for local functions.  */
+extern int protlocal (void);
+
+const char *protvarlocal = __FILE__;
+extern const char *protvarinmod;
+extern const char *protvaritcpt;
+
+int
+do_test (void)
+{
+  int res = 0;
+  int val;
+
+  /* First test: check whether .protected is handled correctly by the
+     assembler/linker.  The uses of `protlocal' in the DSOs and in the
+     main program should all be resolved with the local definitions.  */
+  val = protlocal () + calllocal1 () + calllocal2 ();
+  if (val != 0x155)
+    {
+      puts ("\
+The handling of `.protected' seems to be implemented incorrectly: giving up");
+      abort ();
+    }
+  puts ("`.protected' seems to be handled correctly, good!");
+
+  /* Function pointers: for functions which are marked local and for
+     which definitions are available all function pointers must be
+     distinct.  */
+  if (protlocal == getlocal1 ())
+    {
+      puts ("`protlocal' in main and mod1 have same address");
+      res = 1;
+    }
+  if (protlocal == getlocal2 ())
+    {
+      puts ("`protlocal' in main and mod2 have same address");
+      res = 1;
+    }
+  if (getlocal1 () == getlocal2 ())
+    {
+      puts ("`protlocal' in mod1 and mod2 have same address");
+      res = 1;
+    }
+  if (getlocal1 () () + getlocal2 () () != 0x44)
+    {
+      puts ("pointers to `protlocal' in mod1 or mod2 incorrect");
+      res = 1;
+    }
+
+  /* Next test.  This is similar to the last one but the function we
+     are calling is not defined in the main object.  This means that
+     the invocation in the main object uses the definition in the
+     first DSO.  */
+  if (protinmod != getinmod1 ())
+    {
+      printf ("&protinmod in main (%p) != &protinmod in mod1 (%p)\n",
+	      protinmod, getinmod1 ());
+      res = 1;
+    }
+  if (protinmod == getinmod2 ())
+    {
+      puts ("`protinmod' in main and mod2 have same address");
+      res = 1;
+    }
+  if (getinmod1 () == getinmod2 ())
+    {
+      puts ("`protinmod' in mod1 and mod2 have same address");
+      res = 1;
+    }
+  if (protinmod () + getinmod1 () () + getinmod2 () () != 0x4800)
+    {
+      puts ("pointers to `protinmod' in mod1 or mod2 incorrect");
+      res = 1;
+    }
+  val = protinmod () + callinmod1 () + callinmod2 ();
+  if (val != 0x15800)
+    {
+      printf ("calling of `protinmod' leads to wrong result (%#x)\n", val);
+      res = 1;
+    }
+
+  /* A very similar text.  Same setup for the main object and the modules
+     but this time we have another definition in a preloaded module. This
+     one intercepts the references from the main object.  */
+  if (protitcpt != getitcpt3 ())
+    {
+      printf ("&protitcpt in main (%p) != &protitcpt in mod3 (%p)\n",
+	      &protitcpt, getitcpt3 ());
+      res = 1;
+    }
+  if (protitcpt == getitcpt1 ())
+    {
+      puts ("`protitcpt' in main and mod1 have same address");
+      res = 1;
+    }
+  if (protitcpt == getitcpt2 ())
+    {
+      puts ("`protitcpt' in main and mod2 have same address");
+      res = 1;
+    }
+  if (getitcpt1 () == getitcpt2 ())
+    {
+      puts ("`protitcpt' in mod1 and mod2 have same address");
+      res = 1;
+    }
+  val = protitcpt () + getitcpt1 () () + getitcpt2 () () + getitcpt3 () ();
+  if (val != 0x8440000)
+    {
+      printf ("\
+pointers to `protitcpt' in mod1 or mod2 or mod3 incorrect (%#x)\n", val);
+      res = 1;
+    }
+  val = protitcpt () + callitcpt1 () + callitcpt2 () + callitcpt3 ();
+  if (val != 0x19540000)
+    {
+      printf ("calling of `protitcpt' leads to wrong result (%#x)\n", val);
+      res = 1;
+    }
+
+  /* Now look at variables.  First a variable which is available
+     everywhere.  We must have three different addresses.  */
+  if (&protvarlocal == getvarlocal1 ())
+    {
+      puts ("`protvarlocal' in main and mod1 have same address");
+      res = 1;
+    }
+  if (&protvarlocal == getvarlocal2 ())
+    {
+      puts ("`protvarlocal' in main and mod2 have same address");
+      res = 1;
+    }
+  if (getvarlocal1 () == getvarlocal2 ())
+    {
+      puts ("`protvarlocal' in mod1 and mod2 have same address");
+      res = 1;
+    }
+  if (strcmp (protvarlocal, __FILE__) != 0)
+    {
+      puts ("`protvarlocal in main has wrong value");
+      res = 1;
+    }
+  if (strcmp (*getvarlocal1 (), "vismod1.c") != 0)
+    {
+      puts ("`getvarlocal1' returns wrong value");
+      res = 1;
+    }
+  if (strcmp (*getvarlocal2 (), "vismod2.c") != 0)
+    {
+      puts ("`getvarlocal2' returns wrong value");
+      res = 1;
+    }
+
+  /* Now the case where there is no local definition.  */
+  if (&protvarinmod != getvarinmod1 ())
+    {
+      printf ("&protvarinmod in main (%p) != &protitcpt in mod1 (%p)\n",
+	      &protvarinmod, getvarinmod1 ());
+      // XXX Possibly enable once fixed.
+      // res = 1;
+    }
+  if (&protvarinmod == getvarinmod2 ())
+    {
+      puts ("`protvarinmod' in main and mod2 have same address");
+      res = 1;
+    }
+  if (strcmp (*getvarinmod1 (), "vismod1.c") != 0)
+    {
+      puts ("`getvarinmod1' returns wrong value");
+      res = 1;
+    }
+  if (strcmp (*getvarinmod2 (), "vismod2.c") != 0)
+    {
+      puts ("`getvarinmod2' returns wrong value");
+      res = 1;
+    }
+
+  /* And a test where a variable definition is intercepted.  */
+  if (&protvaritcpt == getvaritcpt1 ())
+    {
+      puts ("`protvaritcpt' in main and mod1 have same address");
+      res = 1;
+    }
+  if (&protvaritcpt == getvaritcpt2 ())
+    {
+      puts ("`protvaritcpt' in main and mod2 have same address");
+      res = 1;
+    }
+  if (&protvaritcpt != getvaritcpt3 ())
+    {
+      printf ("&protvaritcpt in main (%p) != &protvaritcpt in mod3 (%p)\n",
+	      &protvaritcpt, getvaritcpt3 ());
+      // XXX Possibly enable once fixed.
+      // res = 1;
+    }
+  if (getvaritcpt1 () == getvaritcpt2 ())
+    {
+      puts ("`protvaritcpt' in mod1 and mod2 have same address");
+      res = 1;
+    }
+  if (strcmp (protvaritcpt, "vismod3.c") != 0)
+    {
+      puts ("`protvaritcpt in main has wrong value");
+      res = 1;
+    }
+  if (strcmp (*getvaritcpt1 (), "vismod1.c") != 0)
+    {
+      puts ("`getvaritcpt1' returns wrong value");
+      res = 1;
+    }
+  if (strcmp (*getvaritcpt2 (), "vismod2.c") != 0)
+    {
+      puts ("`getvaritcpt2' returns wrong value");
+      res = 1;
+    }
+
+  return res;
+}
+
+
+int
+protlocal (void)
+{
+  return 0x1;
+}
diff --git a/REORG.TODO/elf/vismod.h b/REORG.TODO/elf/vismod.h
new file mode 100644
index 0000000000..ef05ffd5e9
--- /dev/null
+++ b/REORG.TODO/elf/vismod.h
@@ -0,0 +1,27 @@
+/* Prototypes for the functions in the DSOs.  */
+extern int calllocal1 (void);
+extern int (*getlocal1 (void)) (void);
+extern int callinmod1 (void);
+extern int (*getinmod1 (void)) (void);
+extern int callitcpt1 (void);
+extern int (*getitcpt1 (void)) (void);
+extern const char **getvarlocal1 (void);
+extern const char **getvarinmod1 (void);
+extern const char **getvaritcpt1 (void);
+extern int calllocal2 (void);
+extern int (*getlocal2 (void)) (void);
+extern int callinmod2 (void);
+extern int (*getinmod2 (void)) (void);
+extern int callitcpt2 (void);
+extern int (*getitcpt2 (void)) (void);
+extern const char **getvarlocal2 (void);
+extern const char **getvarinmod2 (void);
+extern const char **getvaritcpt2 (void);
+extern int callitcpt3 (void);
+extern int (*getitcpt3 (void)) (void);
+extern const char **getvaritcpt3 (void);
+
+extern int protinmod (void);
+extern int protitcpt (void);
+extern int protlocal (void);
+
diff --git a/REORG.TODO/elf/vismod1.c b/REORG.TODO/elf/vismod1.c
new file mode 100644
index 0000000000..3e56404ce7
--- /dev/null
+++ b/REORG.TODO/elf/vismod1.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "vismod.h"
+
+int
+protlocal (void)
+{
+  return 0x4;
+}
+asm (".protected protlocal");
+
+
+int
+calllocal1 (void)
+{
+  return protlocal () + 0x10;
+}
+
+int
+(*getlocal1 (void)) (void)
+{
+  return protlocal;
+}
+
+int
+protinmod (void)
+{
+  return 0x400;
+}
+asm (".protected protinmod");
+
+int
+callinmod1 (void)
+{
+  return protinmod () + 0x1000;
+}
+
+int
+(*getinmod1 (void)) (void)
+{
+  return protinmod;
+}
+
+int
+protitcpt (void)
+{
+  return 0x40000;
+}
+asm (".protected protitcpt");
+
+int
+callitcpt1 (void)
+{
+  return protitcpt () + 0x100000;
+}
+
+int
+(*getitcpt1 (void)) (void)
+{
+  return protitcpt;
+}
+
+const char *protvarlocal = __FILE__;
+asm (".protected protvarlocal");
+
+const char **
+getvarlocal1 (void)
+{
+  return &protvarlocal;
+}
+
+const char *protvarinmod = __FILE__;
+asm (".protected protvarinmod");
+
+const char **
+getvarinmod1 (void)
+{
+  return &protvarinmod;
+}
+
+const char *protvaritcpt = __FILE__;
+asm (".protected protvaritcpt");
+
+const char **
+getvaritcpt1 (void)
+{
+  return &protvaritcpt;
+}
diff --git a/REORG.TODO/elf/vismod2.c b/REORG.TODO/elf/vismod2.c
new file mode 100644
index 0000000000..89be69728a
--- /dev/null
+++ b/REORG.TODO/elf/vismod2.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include "vismod.h"
+
+int
+protlocal (void)
+{
+  return 0x40;
+}
+asm (".protected protlocal");
+
+
+int
+calllocal2 (void)
+{
+  return protlocal () + 0x100;
+}
+
+int
+(*getlocal2 (void)) (void)
+{
+  return protlocal;
+}
+
+int
+protinmod (void)
+{
+  return 0x4000;
+}
+asm (".protected protinmod");
+
+int
+callinmod2 (void)
+{
+  return protinmod () + 0x10000;
+}
+
+int
+(*getinmod2 (void)) (void)
+{
+  return protinmod;
+}
+
+int
+protitcpt (void)
+{
+  return 0x400000;
+}
+asm (".protected protitcpt");
+
+int
+callitcpt2 (void)
+{
+  return protitcpt () + 0x1000000;
+}
+
+int
+(*getitcpt2 (void)) (void)
+{
+  return protitcpt;
+}
+
+const char *protvarlocal = __FILE__;
+asm (".protected protvarlocal");
+
+const char **
+getvarlocal2 (void)
+{
+  return &protvarlocal;
+}
+
+const char *protvarinmod = __FILE__;
+asm (".protected protvarinmod");
+
+const char **
+getvarinmod2 (void)
+{
+  return &protvarinmod;
+}
+
+const char *protvaritcpt = __FILE__;
+asm (".protected protvaritcpt");
+
+const char **
+getvaritcpt2 (void)
+{
+  return &protvaritcpt;
+}
+
+/* We must never call these functions.  */
+int
+callitcpt3 (void)
+{
+  abort ();
+}
+
+int
+(*getitcpt3 (void)) (void)
+{
+  abort ();
+}
+
+const char **
+getvaritcpt3 (void)
+{
+  abort ();
+}
diff --git a/REORG.TODO/elf/vismod3.c b/REORG.TODO/elf/vismod3.c
new file mode 100644
index 0000000000..1074d1bcda
--- /dev/null
+++ b/REORG.TODO/elf/vismod3.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "vismod.h"
+
+int
+protitcpt (void)
+{
+  return 0x4000000;
+}
+asm (".protected protitcpt");
+
+int
+callitcpt3 (void)
+{
+  return protitcpt () + 0x10000000;
+}
+
+int
+(*getitcpt3 (void)) (void)
+{
+  return protitcpt;
+}
+
+const char *protvaritcpt = __FILE__;
+asm (".protected protvaritcpt");
+
+const char **
+getvaritcpt3 (void)
+{
+  return &protvaritcpt;
+}