1212#include <sys/utsname.h>
1313#include <sys/param.h>
1414#include <sys/stat.h>
15+ #include <sys/mman.h>
1516#include <linux/kernel.h>
1617#include <linux/err.h>
1718#include <linux/btf.h>
@@ -120,6 +121,9 @@ struct btf {
120121 /* whether base_btf should be freed in btf_free for this instance */
121122 bool owns_base ;
122123
124+ /* whether raw_data is a (read-only) mmap */
125+ bool raw_data_is_mmap ;
126+
123127 /* BTF object FD, if loaded into kernel */
124128 int fd ;
125129
@@ -951,6 +955,17 @@ static bool btf_is_modifiable(const struct btf *btf)
951955 return (void * )btf -> hdr != btf -> raw_data ;
952956}
953957
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+
954969void btf__free (struct btf * btf )
955970{
956971 if (IS_ERR_OR_NULL (btf ))
@@ -970,7 +985,7 @@ void btf__free(struct btf *btf)
970985 free (btf -> types_data );
971986 strset__free (btf -> strs_set );
972987 }
973- free (btf -> raw_data );
988+ btf_free_raw_data (btf );
974989 free (btf -> raw_data_swapped );
975990 free (btf -> type_offs );
976991 if (btf -> owns_base )
@@ -1030,7 +1045,7 @@ struct btf *btf__new_empty_split(struct btf *base_btf)
10301045 return libbpf_ptr (btf_new_empty (base_btf ));
10311046}
10321047
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 )
10341049{
10351050 struct btf * btf ;
10361051 int err ;
@@ -1050,12 +1065,18 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
10501065 btf -> start_str_off = base_btf -> hdr -> str_len ;
10511066 }
10521067
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 );
10571078 }
1058- memcpy ( btf -> raw_data , data , size );
1079+
10591080 btf -> raw_size = size ;
10601081
10611082 btf -> hdr = btf -> raw_data ;
@@ -1083,12 +1104,12 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
10831104
10841105struct btf * btf__new (const void * data , __u32 size )
10851106{
1086- return libbpf_ptr (btf_new (data , size , NULL ));
1107+ return libbpf_ptr (btf_new (data , size , NULL , false ));
10871108}
10881109
10891110struct btf * btf__new_split (const void * data , __u32 size , struct btf * base_btf )
10901111{
1091- return libbpf_ptr (btf_new (data , size , base_btf ));
1112+ return libbpf_ptr (btf_new (data , size , base_btf , false ));
10921113}
10931114
10941115struct btf_elf_secs {
@@ -1209,7 +1230,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
12091230
12101231 if (secs .btf_base_data ) {
12111232 dist_base_btf = btf_new (secs .btf_base_data -> d_buf , secs .btf_base_data -> d_size ,
1212- NULL );
1233+ NULL , false );
12131234 if (IS_ERR (dist_base_btf )) {
12141235 err = PTR_ERR (dist_base_btf );
12151236 dist_base_btf = NULL ;
@@ -1218,7 +1239,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
12181239 }
12191240
12201241 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 );
12221243 if (IS_ERR (btf )) {
12231244 err = PTR_ERR (btf );
12241245 goto done ;
@@ -1335,7 +1356,7 @@ static struct btf *btf_parse_raw(const char *path, struct btf *base_btf)
13351356 }
13361357
13371358 /* finally parse BTF data */
1338- btf = btf_new (data , sz , base_btf );
1359+ btf = btf_new (data , sz , base_btf , false );
13391360
13401361err_out :
13411362 free (data );
@@ -1354,6 +1375,37 @@ struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf)
13541375 return libbpf_ptr (btf_parse_raw (path , base_btf ));
13551376}
13561377
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+
13571409static struct btf * btf_parse (const char * path , struct btf * base_btf , struct btf_ext * * btf_ext )
13581410{
13591411 struct btf * btf ;
@@ -1618,7 +1670,7 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf)
16181670 goto exit_free ;
16191671 }
16201672
1621- btf = btf_new (ptr , btf_info .btf_size , base_btf );
1673+ btf = btf_new (ptr , btf_info .btf_size , base_btf , false );
16221674
16231675exit_free :
16241676 free (ptr );
@@ -1658,10 +1710,8 @@ struct btf *btf__load_from_kernel_by_id(__u32 id)
16581710
16591711static void btf_invalidate_raw_data (struct btf * btf )
16601712{
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 );
16651715 if (btf -> raw_data_swapped ) {
16661716 free (btf -> raw_data_swapped );
16671717 btf -> raw_data_swapped = NULL ;
@@ -5331,7 +5381,10 @@ struct btf *btf__load_vmlinux_btf(void)
53315381 pr_warn ("kernel BTF is missing at '%s', was CONFIG_DEBUG_INFO_BTF enabled?\n" ,
53325382 sysfs_btf_path );
53335383 } 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+
53355388 if (!btf ) {
53365389 err = - errno ;
53375390 pr_warn ("failed to read kernel BTF from '%s': %s\n" ,
0 commit comments