Gentoo Archives: gentoo-commits

From: Michael Haubenwallner <haubi@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: profiles/prefix/windows/cygwin/
Date: Tue, 07 May 2019 08:06:45
Message-Id: 1557216353.949b7a9801e59a2317cd68da53bdae344cd3e417.haubi@gentoo
1 commit: 949b7a9801e59a2317cd68da53bdae344cd3e417
2 Author: Michael Haubenwallner <haubi <AT> gentoo <DOT> org>
3 AuthorDate: Mon May 6 09:43:11 2019 +0000
4 Commit: Michael Haubenwallner <haubi <AT> gentoo <DOT> org>
5 CommitDate: Tue May 7 08:05:53 2019 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=949b7a98
7
8 prefix/cygwin/profile.bashrc: add the Cygwin rebase hook
9
10 The Cygwin fork can work more reliable when each DLL is loaded at it's
11 preferred base address. The Cygwin rebase hook does maintain these
12 preferred base addresses to be unique across all installed DLLs, using
13 the app-admin/cygwin-rebase utility.
14
15 Signed-off-by: Michael Haubenwallner <haubi <AT> gentoo.org>
16
17 profiles/prefix/windows/cygwin/profile.bashrc | 187 +++++++++++++++++++++++++-
18 1 file changed, 184 insertions(+), 3 deletions(-)
19
20 diff --git a/profiles/prefix/windows/cygwin/profile.bashrc b/profiles/prefix/windows/cygwin/profile.bashrc
21 index dd7e59f331a..aecfd9adb7c 100644
22 --- a/profiles/prefix/windows/cygwin/profile.bashrc
23 +++ b/profiles/prefix/windows/cygwin/profile.bashrc
24 @@ -25,13 +25,194 @@ post_pkg_prerm() {
25 }
26
27 cygwin-post_pkg_preinst() {
28 - :
29 + cygwin-rebase-post_pkg_preinst
30 }
31
32 cygwin-pre_pkg_postinst() {
33 - :
34 + cygwin-rebase-pre_pkg_postinst
35 }
36
37 cygwin-post_pkg_prerm() {
38 - :
39 + cygwin-rebase-post_pkg_prerm
40 +}
41 +
42 +###############################################################################
43 +# To allow a Windows DLL to reside in memory just once for multiple processes,
44 +# each process needs to be able to map that DLL at the same base address,
45 +# without the need for a dynamic rebase. However, this requires the DLL's
46 +# base address to be unique across all DLLs potentially loaded into a single
47 +# process. Hence the PE/COFF binary format allows to define a preferred base
48 +# address for DLLs, but leaves it up to the package manager to maintain that
49 +# base address to be unique across all DLLs related together.
50 +# (Not sure how exactly ASLR plays in here, though.)
51 +#
52 +# Furthermore, for the Cygwin fork, it is crucial that the child process is
53 +# able to reload a DLL at the very same address as in the parent process.
54 +# Having unique preferred base addresses across all related DLLs does help
55 +# here as well.
56 +#
57 +# The Cygwin rebase utility does maintain some database holding the size and
58 +# preferred base address for each DLL, and allows to update a DLL's preferred
59 +# base address to not conflict with already installed DLLs.
60 +#
61 +# As updating the preferred base address for a DLL in use is a bad idea, we
62 +# need to update the base address while the DLL is in staging directory, and
63 +# update the rebase database after merging the DLL to the live file system.
64 +#
65 +# This allows to define a new preferred base address for a DLL that would
66 +# replace an existing one, because during fork we really want to use the
67 +# old version in the child process, which is verified using the preferred
68 +# base address value to be identical in parent and child process.
69 +#
70 +# Otherwise, the new DLL may have identical size and preferred base address
71 +# as the old DLL, and we may not detect a different DLL in the fork child.
72 +#
73 +# For unmerging a DLL: The Cygwin rebase utility does check if a DLL found
74 +# in the database does still exist, removing that database entry otherwise.
75 +###############################################################################
76 +
77 +cygwin-rebase-get_pendingdir() {
78 + echo "var/db/rebase/pending"
79 +}
80 +
81 +cygwin-rebase-get_mergeddir() {
82 + echo "var/db/rebase/merged"
83 +}
84 +
85 +cygwin-rebase-get_listname() {
86 + echo "dlls_${CATEGORY}_${P}${PR:+-}${PR}"
87 +}
88 +
89 +cygwin-rebase-get_rebase_program() {
90 + [[ ${CHOST} == "${CBUILD}" ]] || return 1
91 + local pfx
92 + for pfx in "${EPREFIX}" "${BROOT:-${PORTAGE_OVERRIDE_EPREFIX}}"
93 + do
94 + [[ -x ${pfx}/usr/bin/rebase ]] || continue
95 + echo "${pfx}/usr/bin/rebase"
96 + return 0
97 + done
98 + return 1
99 +}
100 +
101 +cygwin-rebase-post_pkg_preinst() {
102 + # Ensure database is up to date for when dlls were merged but
103 + # subsequent cygwin-rebase-merge-pending was not executed.
104 + einfo "Cygwin: Merging pending files into rebase database..."
105 + cygwin-rebase-merge pending
106 + eend $?
107 +
108 + local listname=$(cygwin-rebase-get_listname)
109 + local pendingdir=$(cygwin-rebase-get_pendingdir)
110 + local rebase_program=$(cygwin-rebase-get_rebase_program)
111 +
112 + if [[ ${CATEGORY}/${PN} == 'app-admin/cygwin-rebase' ]]
113 + then
114 + local mergeddir=$(cygwin-rebase-get_mergeddir)
115 + keepdir "/${pendingdir}"
116 + keepdir "/${mergeddir}"
117 + fi
118 +
119 + einfo "Cygwin: Rebasing new files..."
120 + (
121 + set -e
122 + cd "${ED}"
123 +
124 + # The list of suffixes is found in the rebaseall script.
125 + find . -type f \
126 + '(' -name '*.dll' \
127 + -o -name '*.so' \
128 + -o -name '*.oct' \
129 + ')' \
130 + | sed -e "s|^\.|${EPREFIX}|" > "${T}/rebase-filelist"
131 + [[ "${PIPESTATUS[*]}" == '0 0' ]]
132 +
133 + # Nothing found to rebase in this package.
134 + [[ -s ${T}/rebase-filelist ]] || exit 0
135 +
136 + mkdir -p "./${pendingdir}"
137 + cp -f "${T}/rebase-filelist" "./${pendingdir}/${listname}"
138 +
139 + # Without the rebase program, do not perform a rebase.
140 + [[ ${rebase_program} ]] || exit 0
141 +
142 + sed -ne "/^${EPREFIX//\//\\/}\\//{s|^${EPREFIX}/||;p}" "./${pendingdir}/${listname}" \
143 + | "${rebase_program}" --verbose --oblivious --database --filelist=-
144 + [[ "${PIPESTATUS[*]}" == '0 0' ]]
145 + )
146 + eend $?
147 +}
148 +
149 +cygwin-rebase-pre_pkg_postinst() {
150 + if [[ ${CATEGORY}/${PN} == 'app-admin/cygwin-rebase' ]]
151 + then
152 + einfo "Cygwin: Updating rebase database with installed files..."
153 + cygwin-rebase-merge merged
154 + eend $?
155 + fi
156 + einfo "Cygwin: Merging updated files into rebase database..."
157 + cygwin-rebase-merge pending
158 + eend $?
159 +}
160 +
161 +cygwin-rebase-merge() {
162 + local mode=${1}
163 +
164 + local rebase_program=$(cygwin-rebase-get_rebase_program)
165 + [[ ${rebase_program} ]] || return 0
166 +
167 + local pendingdir=''
168 + local mergeddir=''
169 + case ${mode} in
170 + pending)
171 + pendingdir=$(cygwin-rebase-get_pendingdir)
172 + mergeddir=$(cygwin-rebase-get_mergeddir)
173 + ;;
174 + merged)
175 + pendingdir=$(cygwin-rebase-get_mergeddir)
176 + mergeddir=''
177 + ;;
178 + *)
179 + die "Invalid mode '${mode}'."
180 + ;;
181 + esac
182 +
183 + (
184 + set -e
185 + cd "${EROOT}"
186 +
187 + [[ -r ./${pendingdir}/. ]]
188 + [[ -r ./${mergeddir}/. ]]
189 +
190 + find ./"${pendingdir}" -mindepth 1 -maxdepth 1 -type f -name 'dlls_*' \
191 + -exec sed -ne "/^${EPREFIX//\//\\/}\\//{s|^${EPREFIX}/||;p}" {} + \
192 + | "${rebase_program}" --verbose --merge-files --database --filelist=-
193 + [[ "${PIPESTATUS[*]}" == '0 0' ]]
194 +
195 + [[ ${mode} == 'pending' ]] || exit 0
196 +
197 + find "./${pendingdir}" -maxdepth 1 -type f \
198 + -exec mv -f -t "./${mergeddir}/" {} +
199 + )
200 + [[ $? == 0 ]] || die "Merging ${mode} files into rebase database failed."
201 +}
202 +
203 +cygwin-rebase-post_pkg_prerm() {
204 + # The pending list is installed as part of the package, but
205 + # the merged list is not. Move from merged back to pending,
206 + # in case the unmerge fails...
207 + local pendingdir=$(cygwin-rebase-get_pendingdir)
208 + local mergeddir=$(cygwin-rebase-get_mergeddir)
209 + local listname=$(cygwin-rebase-get_listname)
210 + (
211 + set -e
212 + cd "${EROOT}"
213 + [[ -w ./${mergeddir}/. ]]
214 + [[ -w ./${pendingdir}/. ]]
215 + if [[ -s ./${mergeddir}/${listname} ]]
216 + then
217 + mv -f "./${mergeddir}/${listname}" "./${pendingdir}/${listname}" || :
218 + fi
219 + rm -f "./${mergeddir}/${listname}"
220 + )
221 }