@@ -992,14 +992,29 @@ struct MachOSymbol {
992
992
weak : bool ,
993
993
}
994
994
995
+ /// Parses an integer with nibbles xxxx.yy.zz into a [semver::Version].
996
+ fn parse_version_nibbles ( v : u32 ) -> semver:: Version {
997
+ let major = v >> 16 ;
998
+ let minor = v << 16 >> 24 ;
999
+ let patch = v & 0xff ;
1000
+
1001
+ semver:: Version :: new ( major as _ , minor as _ , patch as _ )
1002
+ }
1003
+
995
1004
fn validate_macho < Mach : MachHeader < Endian = Endianness > > (
996
1005
context : & mut ValidationContext ,
997
1006
target_triple : & str ,
998
1007
python_major_minor : & str ,
1008
+ advertised_target_version : & str ,
1009
+ advertised_sdk_version : & str ,
999
1010
path : & Path ,
1000
1011
header : & Mach ,
1001
1012
bytes : & [ u8 ] ,
1002
1013
) -> Result < ( ) > {
1014
+ let advertised_target_version =
1015
+ semver:: Version :: parse ( & format ! ( "{}.0" , advertised_target_version) ) ?;
1016
+ let advertised_sdk_version = semver:: Version :: parse ( & format ! ( "{}.0" , advertised_sdk_version) ) ?;
1017
+
1003
1018
let endian = header. endian ( ) ?;
1004
1019
1005
1020
let wanted_cpu_type = match target_triple {
@@ -1030,9 +1045,28 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1030
1045
1031
1046
let mut dylib_names = vec ! [ ] ;
1032
1047
let mut undefined_symbols = vec ! [ ] ;
1048
+ let mut target_version = None ;
1049
+ let mut sdk_version = None ;
1033
1050
1034
1051
while let Some ( load_command) = load_commands. next ( ) ? {
1035
1052
match load_command. variant ( ) ? {
1053
+ LoadCommandVariant :: BuildVersion ( v) => {
1054
+ // Sometimes the SDK version is advertised as 0.0.0. In that case just ignore it.
1055
+ let version = parse_version_nibbles ( v. sdk . get ( endian) ) ;
1056
+ if version > semver:: Version :: new ( 0 , 0 , 0 ) {
1057
+ sdk_version = Some ( version) ;
1058
+ }
1059
+
1060
+ target_version = Some ( parse_version_nibbles ( v. minos . get ( endian) ) ) ;
1061
+ }
1062
+ LoadCommandVariant :: VersionMin ( v) => {
1063
+ let version = parse_version_nibbles ( v. sdk . get ( endian) ) ;
1064
+ if version > semver:: Version :: new ( 0 , 0 , 0 ) {
1065
+ sdk_version = Some ( version) ;
1066
+ }
1067
+
1068
+ target_version = Some ( parse_version_nibbles ( v. version . get ( endian) ) ) ;
1069
+ }
1036
1070
LoadCommandVariant :: Dylib ( command) => {
1037
1071
let raw_string = load_command. string ( endian, command. dylib . name . clone ( ) ) ?;
1038
1072
let lib = String :: from_utf8 ( raw_string. to_vec ( ) ) ?;
@@ -1134,6 +1168,28 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1134
1168
}
1135
1169
}
1136
1170
1171
+ if let Some ( actual_target_version) = target_version {
1172
+ if actual_target_version != advertised_target_version {
1173
+ context. errors . push ( format ! (
1174
+ "{} targets SDK {} but JSON advertises SDK {}" ,
1175
+ path. display( ) ,
1176
+ actual_target_version,
1177
+ advertised_target_version
1178
+ ) ) ;
1179
+ }
1180
+ }
1181
+
1182
+ if let Some ( actual_sdk_version) = sdk_version {
1183
+ if actual_sdk_version != advertised_sdk_version {
1184
+ context. errors . push ( format ! (
1185
+ "{} was built with SDK {} but JSON advertises SDK {}" ,
1186
+ path. display( ) ,
1187
+ actual_sdk_version,
1188
+ advertised_sdk_version,
1189
+ ) )
1190
+ }
1191
+ }
1192
+
1137
1193
// Don't perform undefined symbol analysis for object files because the object file
1138
1194
// in isolation lacks context.
1139
1195
if header. filetype ( endian) != MH_OBJECT {
@@ -1248,6 +1304,12 @@ fn validate_possible_object_file(
1248
1304
& mut context,
1249
1305
triple,
1250
1306
python_major_minor,
1307
+ json. apple_sdk_deployment_target
1308
+ . as_ref ( )
1309
+ . expect ( "apple_sdk_deployment_target should be set" ) ,
1310
+ json. apple_sdk_version
1311
+ . as_ref ( )
1312
+ . expect ( "apple_sdk_version should be set" ) ,
1251
1313
path. as_ref ( ) ,
1252
1314
header,
1253
1315
& data,
@@ -1260,6 +1322,12 @@ fn validate_possible_object_file(
1260
1322
& mut context,
1261
1323
triple,
1262
1324
python_major_minor,
1325
+ json. apple_sdk_deployment_target
1326
+ . as_ref ( )
1327
+ . expect ( "apple_sdk_deployment_target should be set" ) ,
1328
+ json. apple_sdk_version
1329
+ . as_ref ( )
1330
+ . expect ( "apple_sdk_version should be set" ) ,
1263
1331
path. as_ref ( ) ,
1264
1332
header,
1265
1333
& data,
0 commit comments