1 /* Sort array of link maps according to dependencies.
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
22 /* Sort array MAPS according to dependencies of the contained objects.
23 Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is
24 called for finishing an object. */
26 _dl_sort_maps (struct link_map
**maps
, unsigned int nmaps
, char *used
,
29 /* A list of one element need not be sorted. */
35 memset (seen
, 0, nmaps
* sizeof (seen
[0]));
38 /* Keep track of which object we looked at this round. */
40 struct link_map
*thisp
= maps
[i
];
42 if (__glibc_unlikely (for_fini
))
44 /* Do not handle ld.so in secondary namespaces and objects which
46 if (thisp
!= thisp
->l_real
|| thisp
->l_idx
== -1)
50 /* Find the last object in the list for which the current one is
51 a dependency and move the current object behind the object
52 with the dependency. */
53 unsigned int k
= nmaps
- 1;
56 struct link_map
**runp
= maps
[k
]->l_initfini
;
58 /* Look through the dependencies of the object. */
60 if (__glibc_unlikely (*runp
++ == thisp
))
63 /* Move the current object to the back past the last
64 object with it as the dependency. */
65 memmove (&maps
[i
], &maps
[i
+ 1],
66 (k
- i
) * sizeof (maps
[0]));
71 char here_used
= used
[i
];
72 memmove (&used
[i
], &used
[i
+ 1],
73 (k
- i
) * sizeof (used
[0]));
77 if (seen
[i
+ 1] > nmaps
- i
)
83 uint16_t this_seen
= seen
[i
];
84 memmove (&seen
[i
], &seen
[i
+ 1], (k
- i
) * sizeof (seen
[0]));
90 if (__glibc_unlikely (for_fini
&& maps
[k
]->l_reldeps
!= NULL
))
92 unsigned int m
= maps
[k
]->l_reldeps
->act
;
93 struct link_map
**relmaps
= &maps
[k
]->l_reldeps
->list
[0];
95 /* Look through the relocation dependencies of the object. */
97 if (__glibc_unlikely (relmaps
[m
] == thisp
))
99 /* If a cycle exists with a link time dependency,
100 preserve the latter. */
101 struct link_map
**runp
= thisp
->l_initfini
;
103 while (*runp
!= NULL
)
104 if (__glibc_unlikely (*runp
++ == maps
[k
]))
118 memset (&seen
[i
], 0, (nmaps
- i
) * sizeof (seen
[0]));