2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
6 #include "elf_versioning.h"
16 assert_defined_image_version(image_t
* dependentImage
, image_t
* image
,
17 const elf_version_info
& neededVersion
, bool weak
)
19 // If the image doesn't have version definitions, we print a warning and
20 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
21 // later when resolving versioned symbols.
22 if (image
->version_definitions
== NULL
) {
23 FATAL("%s: No version information available (required by %s)\n",
24 image
->path
, dependentImage
->path
);
28 // iterate through the defined versions to find the given one
29 elf_verdef
* definition
= image
->version_definitions
;
30 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
31 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
32 elf_version_info
& info
= image
->versions
[versionIndex
];
34 if (neededVersion
.hash
== info
.hash
35 && strcmp(neededVersion
.name
, info
.name
) == 0) {
39 definition
= (elf_verdef
*)((uint8
*)definition
+ definition
->vd_next
);
42 // version not found -- fail, if not weak
44 FATAL("%s: version \"%s\" not found (required by %s)\n", image
->path
,
45 neededVersion
.name
, dependentImage
->name
);
46 return B_MISSING_SYMBOL
;
57 init_image_version_infos(image_t
* image
)
59 // First find out how many version infos we need -- i.e. get the greatest
60 // version index from the defined and needed versions (they use the same
64 if (image
->version_definitions
!= NULL
) {
65 elf_verdef
* definition
= image
->version_definitions
;
66 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
67 if (definition
->vd_version
!= 1) {
68 FATAL("%s: Unsupported version definition revision: %u\n",
69 image
->path
, definition
->vd_version
);
73 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
74 if (versionIndex
> maxIndex
)
75 maxIndex
= versionIndex
;
77 definition
= (elf_verdef
*)
78 ((uint8
*)definition
+ definition
->vd_next
);
82 if (image
->needed_versions
!= NULL
) {
83 elf_verneed
* needed
= image
->needed_versions
;
84 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
85 if (needed
->vn_version
!= 1) {
86 FATAL("%s: Unsupported version needed revision: %u\n",
87 image
->path
, needed
->vn_version
);
92 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
93 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
94 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
95 if (versionIndex
> maxIndex
)
96 maxIndex
= versionIndex
;
98 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
101 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
108 // allocate the version infos
110 = (elf_version_info
*)malloc(sizeof(elf_version_info
) * (maxIndex
+ 1));
111 if (image
->versions
== NULL
) {
112 FATAL("Memory shortage in init_image_version_infos()");
115 image
->num_versions
= maxIndex
+ 1;
117 // init the version infos
119 // version definitions
120 if (image
->version_definitions
!= NULL
) {
121 elf_verdef
* definition
= image
->version_definitions
;
122 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
123 if (definition
->vd_cnt
> 0
124 && (definition
->vd_flags
& VER_FLG_BASE
) == 0) {
126 = (elf_verdaux
*)((uint8
*)definition
+ definition
->vd_aux
);
128 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
129 elf_version_info
& info
= image
->versions
[versionIndex
];
130 info
.hash
= definition
->vd_hash
;
131 info
.name
= STRING(image
, verdaux
->vda_name
);
132 info
.file_name
= NULL
;
135 definition
= (elf_verdef
*)
136 ((uint8
*)definition
+ definition
->vd_next
);
141 if (image
->needed_versions
!= NULL
) {
142 elf_verneed
* needed
= image
->needed_versions
;
143 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
144 const char* fileName
= STRING(image
, needed
->vn_file
);
147 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
148 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
149 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
150 elf_version_info
& info
= image
->versions
[versionIndex
];
151 info
.hash
= vernaux
->vna_hash
;
152 info
.name
= STRING(image
, vernaux
->vna_name
);
153 info
.file_name
= fileName
;
155 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
158 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
167 check_needed_image_versions(image_t
* image
)
169 if (image
->needed_versions
== NULL
)
172 elf_verneed
* needed
= image
->needed_versions
;
173 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
174 const char* fileName
= STRING(image
, needed
->vn_file
);
175 image_t
* dependency
= find_loaded_image_by_name(fileName
,
177 if (dependency
== NULL
) {
178 // This can't really happen, unless the object file is broken, since
179 // the file should also appear in DT_NEEDED.
180 FATAL("%s: Version dependency \"%s\" not found", image
->path
,
182 return B_FILE_NOT_FOUND
;
186 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
187 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
188 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
189 elf_version_info
& info
= image
->versions
[versionIndex
];
191 status_t error
= assert_defined_image_version(image
, dependency
,
192 info
, (vernaux
->vna_flags
& VER_FLG_WEAK
) != 0);
196 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
199 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);