@@ -132,14 +132,33 @@ fn get_llvm_object_symbols(
132
132
if err. is_null ( ) {
133
133
return Ok ( true ) ;
134
134
} else {
135
- return Err ( unsafe { * Box :: from_raw ( err as * mut io:: Error ) } ) ;
135
+ let error = unsafe { * Box :: from_raw ( err as * mut io:: Error ) } ;
136
+ // These are the magic constants for LLVM bitcode files:
137
+ // https://github.com/llvm/llvm-project/blob/7eadc1960d199676f04add402bb0aa6f65b7b234/llvm/lib/BinaryFormat/Magic.cpp#L90-L97
138
+ if buf. starts_with ( & [ 0xDE , 0xCE , 0x17 , 0x0B ] ) || buf. starts_with ( & [ b'B' , b'C' , 0xC0 , 0xDE ] )
139
+ {
140
+ // For LLVM bitcode, failure to read the symbols is not fatal. The bitcode may have been
141
+ // produced by a newer LLVM version that the one linked to rustc. This is fine provided
142
+ // that the linker does use said newer LLVM version. We skip writing the symbols for the
143
+ // bitcode to the symbol table of the archive. Traditional linkers don't like this, but
144
+ // newer linkers like lld, mold and wild ignore the symbol table anyway, so if they link
145
+ // against a new enough LLVM it will work out in the end.
146
+ // LLVM's archive writer also has this same behavior of only warning about invalid
147
+ // bitcode since https://github.com/llvm/llvm-project/pull/96848
148
+
149
+ // We don't have access to the DiagCtxt here to produce a nice warning in the correct format.
150
+ eprintln ! ( "warning: Failed to read symbol table from LLVM bitcode: {}" , error) ;
151
+ return Ok ( true ) ;
152
+ } else {
153
+ return Err ( error) ;
154
+ }
136
155
}
137
156
138
157
unsafe extern "C" fn callback ( state : * mut c_void , symbol_name : * const c_char ) -> * mut c_void {
139
158
let f = unsafe { & mut * ( state as * mut & mut dyn FnMut ( & [ u8 ] ) -> io:: Result < ( ) > ) } ;
140
159
match f ( unsafe { CStr :: from_ptr ( symbol_name) } . to_bytes ( ) ) {
141
160
Ok ( ( ) ) => std:: ptr:: null_mut ( ) ,
142
- Err ( err) => Box :: into_raw ( Box :: new ( err) ) as * mut c_void ,
161
+ Err ( err) => Box :: into_raw ( Box :: new ( err) as Box < io :: Error > ) as * mut c_void ,
143
162
}
144
163
}
145
164
@@ -148,7 +167,7 @@ fn get_llvm_object_symbols(
148
167
Box :: into_raw ( Box :: new ( io:: Error :: new (
149
168
io:: ErrorKind :: Other ,
150
169
format ! ( "LLVM error: {}" , error. to_string_lossy( ) ) ,
151
- ) ) ) as * mut c_void
170
+ ) ) as Box < io :: Error > ) as * mut c_void
152
171
}
153
172
}
154
173
0 commit comments