12
12
#include <sys/utsname.h>
13
13
#include <sys/param.h>
14
14
#include <sys/stat.h>
15
+ #include <sys/mman.h>
15
16
#include <linux/kernel.h>
16
17
#include <linux/err.h>
17
18
#include <linux/btf.h>
@@ -120,6 +121,9 @@ struct btf {
120
121
/* whether base_btf should be freed in btf_free for this instance */
121
122
bool owns_base ;
122
123
124
+ /* whether raw_data is a (read-only) mmap */
125
+ bool raw_data_is_mmap ;
126
+
123
127
/* BTF object FD, if loaded into kernel */
124
128
int fd ;
125
129
@@ -951,6 +955,17 @@ static bool btf_is_modifiable(const struct btf *btf)
951
955
return (void * )btf -> hdr != btf -> raw_data ;
952
956
}
953
957
958
+ static void btf_free_raw_data (struct btf * btf )
959
+ {
960
+ if (btf -> raw_data_is_mmap ) {
961
+ munmap (btf -> raw_data , btf -> raw_size );
962
+ btf -> raw_data_is_mmap = false;
963
+ } else {
964
+ free (btf -> raw_data );
965
+ }
966
+ btf -> raw_data = NULL ;
967
+ }
968
+
954
969
void btf__free (struct btf * btf )
955
970
{
956
971
if (IS_ERR_OR_NULL (btf ))
@@ -970,7 +985,7 @@ void btf__free(struct btf *btf)
970
985
free (btf -> types_data );
971
986
strset__free (btf -> strs_set );
972
987
}
973
- free (btf -> raw_data );
988
+ btf_free_raw_data (btf );
974
989
free (btf -> raw_data_swapped );
975
990
free (btf -> type_offs );
976
991
if (btf -> owns_base )
@@ -1030,7 +1045,7 @@ struct btf *btf__new_empty_split(struct btf *base_btf)
1030
1045
return libbpf_ptr (btf_new_empty (base_btf ));
1031
1046
}
1032
1047
1033
- static struct btf * btf_new (const void * data , __u32 size , struct btf * base_btf )
1048
+ static struct btf * btf_new (const void * data , __u32 size , struct btf * base_btf , bool is_mmap )
1034
1049
{
1035
1050
struct btf * btf ;
1036
1051
int err ;
@@ -1050,12 +1065,18 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
1050
1065
btf -> start_str_off = base_btf -> hdr -> str_len ;
1051
1066
}
1052
1067
1053
- btf -> raw_data = malloc (size );
1054
- if (!btf -> raw_data ) {
1055
- err = - ENOMEM ;
1056
- goto done ;
1068
+ if (is_mmap ) {
1069
+ btf -> raw_data = (void * )data ;
1070
+ btf -> raw_data_is_mmap = true;
1071
+ } else {
1072
+ btf -> raw_data = malloc (size );
1073
+ if (!btf -> raw_data ) {
1074
+ err = - ENOMEM ;
1075
+ goto done ;
1076
+ }
1077
+ memcpy (btf -> raw_data , data , size );
1057
1078
}
1058
- memcpy ( btf -> raw_data , data , size );
1079
+
1059
1080
btf -> raw_size = size ;
1060
1081
1061
1082
btf -> hdr = btf -> raw_data ;
@@ -1083,12 +1104,12 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
1083
1104
1084
1105
struct btf * btf__new (const void * data , __u32 size )
1085
1106
{
1086
- return libbpf_ptr (btf_new (data , size , NULL ));
1107
+ return libbpf_ptr (btf_new (data , size , NULL , false ));
1087
1108
}
1088
1109
1089
1110
struct btf * btf__new_split (const void * data , __u32 size , struct btf * base_btf )
1090
1111
{
1091
- return libbpf_ptr (btf_new (data , size , base_btf ));
1112
+ return libbpf_ptr (btf_new (data , size , base_btf , false ));
1092
1113
}
1093
1114
1094
1115
struct btf_elf_secs {
@@ -1209,7 +1230,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
1209
1230
1210
1231
if (secs .btf_base_data ) {
1211
1232
dist_base_btf = btf_new (secs .btf_base_data -> d_buf , secs .btf_base_data -> d_size ,
1212
- NULL );
1233
+ NULL , false );
1213
1234
if (IS_ERR (dist_base_btf )) {
1214
1235
err = PTR_ERR (dist_base_btf );
1215
1236
dist_base_btf = NULL ;
@@ -1218,7 +1239,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
1218
1239
}
1219
1240
1220
1241
btf = btf_new (secs .btf_data -> d_buf , secs .btf_data -> d_size ,
1221
- dist_base_btf ?: base_btf );
1242
+ dist_base_btf ?: base_btf , false );
1222
1243
if (IS_ERR (btf )) {
1223
1244
err = PTR_ERR (btf );
1224
1245
goto done ;
@@ -1335,7 +1356,7 @@ static struct btf *btf_parse_raw(const char *path, struct btf *base_btf)
1335
1356
}
1336
1357
1337
1358
/* finally parse BTF data */
1338
- btf = btf_new (data , sz , base_btf );
1359
+ btf = btf_new (data , sz , base_btf , false );
1339
1360
1340
1361
err_out :
1341
1362
free (data );
@@ -1354,6 +1375,37 @@ struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf)
1354
1375
return libbpf_ptr (btf_parse_raw (path , base_btf ));
1355
1376
}
1356
1377
1378
+ static struct btf * btf_parse_raw_mmap (const char * path , struct btf * base_btf )
1379
+ {
1380
+ struct stat st ;
1381
+ void * data ;
1382
+ struct btf * btf ;
1383
+ int fd , err ;
1384
+
1385
+ fd = open (path , O_RDONLY );
1386
+ if (fd < 0 )
1387
+ return libbpf_err_ptr (- errno );
1388
+
1389
+ if (fstat (fd , & st ) < 0 ) {
1390
+ err = - errno ;
1391
+ close (fd );
1392
+ return libbpf_err_ptr (err );
1393
+ }
1394
+
1395
+ data = mmap (NULL , st .st_size , PROT_READ , MAP_PRIVATE , fd , 0 );
1396
+ err = - errno ;
1397
+ close (fd );
1398
+
1399
+ if (data == MAP_FAILED )
1400
+ return libbpf_err_ptr (err );
1401
+
1402
+ btf = btf_new (data , st .st_size , base_btf , true);
1403
+ if (IS_ERR (btf ))
1404
+ munmap (data , st .st_size );
1405
+
1406
+ return btf ;
1407
+ }
1408
+
1357
1409
static struct btf * btf_parse (const char * path , struct btf * base_btf , struct btf_ext * * btf_ext )
1358
1410
{
1359
1411
struct btf * btf ;
@@ -1618,7 +1670,7 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf)
1618
1670
goto exit_free ;
1619
1671
}
1620
1672
1621
- btf = btf_new (ptr , btf_info .btf_size , base_btf );
1673
+ btf = btf_new (ptr , btf_info .btf_size , base_btf , false );
1622
1674
1623
1675
exit_free :
1624
1676
free (ptr );
@@ -1658,10 +1710,8 @@ struct btf *btf__load_from_kernel_by_id(__u32 id)
1658
1710
1659
1711
static void btf_invalidate_raw_data (struct btf * btf )
1660
1712
{
1661
- if (btf -> raw_data ) {
1662
- free (btf -> raw_data );
1663
- btf -> raw_data = NULL ;
1664
- }
1713
+ if (btf -> raw_data )
1714
+ btf_free_raw_data (btf );
1665
1715
if (btf -> raw_data_swapped ) {
1666
1716
free (btf -> raw_data_swapped );
1667
1717
btf -> raw_data_swapped = NULL ;
@@ -5331,7 +5381,10 @@ struct btf *btf__load_vmlinux_btf(void)
5331
5381
pr_warn ("kernel BTF is missing at '%s', was CONFIG_DEBUG_INFO_BTF enabled?\n" ,
5332
5382
sysfs_btf_path );
5333
5383
} else {
5334
- btf = btf__parse (sysfs_btf_path , NULL );
5384
+ btf = btf_parse_raw_mmap (sysfs_btf_path , NULL );
5385
+ if (IS_ERR (btf ))
5386
+ btf = btf__parse (sysfs_btf_path , NULL );
5387
+
5335
5388
if (!btf ) {
5336
5389
err = - errno ;
5337
5390
pr_warn ("failed to read kernel BTF from '%s': %s\n" ,
0 commit comments