3
3
4
4
#include <uapi/linux/btf.h>
5
5
#include <uapi/linux/types.h>
6
+ #include <linux/seq_file.h>
6
7
#include <linux/compiler.h>
7
8
#include <linux/errno.h>
8
9
#include <linux/slab.h>
@@ -256,6 +257,9 @@ struct btf_kind_operations {
256
257
const struct btf_type * member_type );
257
258
void (* log_details )(struct btf_verifier_env * env ,
258
259
const struct btf_type * t );
260
+ void (* seq_show )(const struct btf * btf , const struct btf_type * t ,
261
+ u32 type_id , void * data , u8 bits_offsets ,
262
+ struct seq_file * m );
259
263
};
260
264
261
265
static const struct btf_kind_operations * const kind_ops [NR_BTF_KINDS ];
@@ -781,6 +785,13 @@ static int btf_df_resolve(struct btf_verifier_env *env,
781
785
return - EINVAL ;
782
786
}
783
787
788
+ static void btf_df_seq_show (const struct btf * btf , const struct btf_type * t ,
789
+ u32 type_id , void * data , u8 bits_offsets ,
790
+ struct seq_file * m )
791
+ {
792
+ seq_printf (m , "<unsupported kind:%u>" , BTF_INFO_KIND (t -> info ));
793
+ }
794
+
784
795
static int btf_int_check_member (struct btf_verifier_env * env ,
785
796
const struct btf_type * struct_type ,
786
797
const struct btf_member * member ,
@@ -879,11 +890,96 @@ static void btf_int_log(struct btf_verifier_env *env,
879
890
btf_int_encoding_str (BTF_INT_ENCODING (int_data )));
880
891
}
881
892
893
+ static void btf_int_bits_seq_show (const struct btf * btf ,
894
+ const struct btf_type * t ,
895
+ void * data , u8 bits_offset ,
896
+ struct seq_file * m )
897
+ {
898
+ u32 int_data = btf_type_int (t );
899
+ u16 nr_bits = BTF_INT_BITS (int_data );
900
+ u16 total_bits_offset ;
901
+ u16 nr_copy_bytes ;
902
+ u16 nr_copy_bits ;
903
+ u8 nr_upper_bits ;
904
+ union {
905
+ u64 u64_num ;
906
+ u8 u8_nums [8 ];
907
+ } print_num ;
908
+
909
+ total_bits_offset = bits_offset + BTF_INT_OFFSET (int_data );
910
+ data += BITS_ROUNDDOWN_BYTES (total_bits_offset );
911
+ bits_offset = BITS_PER_BYTE_MASKED (total_bits_offset );
912
+ nr_copy_bits = nr_bits + bits_offset ;
913
+ nr_copy_bytes = BITS_ROUNDUP_BYTES (nr_copy_bits );
914
+
915
+ print_num .u64_num = 0 ;
916
+ memcpy (& print_num .u64_num , data , nr_copy_bytes );
917
+
918
+ /* Ditch the higher order bits */
919
+ nr_upper_bits = BITS_PER_BYTE_MASKED (nr_copy_bits );
920
+ if (nr_upper_bits ) {
921
+ /* We need to mask out some bits of the upper byte. */
922
+ u8 mask = (1 << nr_upper_bits ) - 1 ;
923
+
924
+ print_num .u8_nums [nr_copy_bytes - 1 ] &= mask ;
925
+ }
926
+
927
+ print_num .u64_num >>= bits_offset ;
928
+
929
+ seq_printf (m , "0x%llx" , print_num .u64_num );
930
+ }
931
+
932
+ static void btf_int_seq_show (const struct btf * btf , const struct btf_type * t ,
933
+ u32 type_id , void * data , u8 bits_offset ,
934
+ struct seq_file * m )
935
+ {
936
+ u32 int_data = btf_type_int (t );
937
+ u8 encoding = BTF_INT_ENCODING (int_data );
938
+ bool sign = encoding & BTF_INT_SIGNED ;
939
+ u32 nr_bits = BTF_INT_BITS (int_data );
940
+
941
+ if (bits_offset || BTF_INT_OFFSET (int_data ) ||
942
+ BITS_PER_BYTE_MASKED (nr_bits )) {
943
+ btf_int_bits_seq_show (btf , t , data , bits_offset , m );
944
+ return ;
945
+ }
946
+
947
+ switch (nr_bits ) {
948
+ case 64 :
949
+ if (sign )
950
+ seq_printf (m , "%lld" , * (s64 * )data );
951
+ else
952
+ seq_printf (m , "%llu" , * (u64 * )data );
953
+ break ;
954
+ case 32 :
955
+ if (sign )
956
+ seq_printf (m , "%d" , * (s32 * )data );
957
+ else
958
+ seq_printf (m , "%u" , * (u32 * )data );
959
+ break ;
960
+ case 16 :
961
+ if (sign )
962
+ seq_printf (m , "%d" , * (s16 * )data );
963
+ else
964
+ seq_printf (m , "%u" , * (u16 * )data );
965
+ break ;
966
+ case 8 :
967
+ if (sign )
968
+ seq_printf (m , "%d" , * (s8 * )data );
969
+ else
970
+ seq_printf (m , "%u" , * (u8 * )data );
971
+ break ;
972
+ default :
973
+ btf_int_bits_seq_show (btf , t , data , bits_offset , m );
974
+ }
975
+ }
976
+
882
977
static const struct btf_kind_operations int_ops = {
883
978
.check_meta = btf_int_check_meta ,
884
979
.resolve = btf_df_resolve ,
885
980
.check_member = btf_int_check_member ,
886
981
.log_details = btf_int_log ,
982
+ .seq_show = btf_int_seq_show ,
887
983
};
888
984
889
985
static int btf_modifier_check_member (struct btf_verifier_env * env ,
@@ -1054,6 +1150,24 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
1054
1150
return 0 ;
1055
1151
}
1056
1152
1153
+ static void btf_modifier_seq_show (const struct btf * btf ,
1154
+ const struct btf_type * t ,
1155
+ u32 type_id , void * data ,
1156
+ u8 bits_offset , struct seq_file * m )
1157
+ {
1158
+ t = btf_type_id_resolve (btf , & type_id );
1159
+
1160
+ btf_type_ops (t )-> seq_show (btf , t , type_id , data , bits_offset , m );
1161
+ }
1162
+
1163
+ static void btf_ptr_seq_show (const struct btf * btf , const struct btf_type * t ,
1164
+ u32 type_id , void * data , u8 bits_offset ,
1165
+ struct seq_file * m )
1166
+ {
1167
+ /* It is a hashed value */
1168
+ seq_printf (m , "%p" , * (void * * )data );
1169
+ }
1170
+
1057
1171
static void btf_ref_type_log (struct btf_verifier_env * env ,
1058
1172
const struct btf_type * t )
1059
1173
{
@@ -1065,20 +1179,23 @@ static struct btf_kind_operations modifier_ops = {
1065
1179
.resolve = btf_modifier_resolve ,
1066
1180
.check_member = btf_modifier_check_member ,
1067
1181
.log_details = btf_ref_type_log ,
1182
+ .seq_show = btf_modifier_seq_show ,
1068
1183
};
1069
1184
1070
1185
static struct btf_kind_operations ptr_ops = {
1071
1186
.check_meta = btf_ref_type_check_meta ,
1072
1187
.resolve = btf_ptr_resolve ,
1073
1188
.check_member = btf_ptr_check_member ,
1074
1189
.log_details = btf_ref_type_log ,
1190
+ .seq_show = btf_ptr_seq_show ,
1075
1191
};
1076
1192
1077
1193
static struct btf_kind_operations fwd_ops = {
1078
1194
.check_meta = btf_ref_type_check_meta ,
1079
1195
.resolve = btf_df_resolve ,
1080
1196
.check_member = btf_df_check_member ,
1081
1197
.log_details = btf_ref_type_log ,
1198
+ .seq_show = btf_df_seq_show ,
1082
1199
};
1083
1200
1084
1201
static int btf_array_check_member (struct btf_verifier_env * env ,
@@ -1209,11 +1326,36 @@ static void btf_array_log(struct btf_verifier_env *env,
1209
1326
array -> type , array -> index_type , array -> nelems );
1210
1327
}
1211
1328
1329
+ static void btf_array_seq_show (const struct btf * btf , const struct btf_type * t ,
1330
+ u32 type_id , void * data , u8 bits_offset ,
1331
+ struct seq_file * m )
1332
+ {
1333
+ const struct btf_array * array = btf_type_array (t );
1334
+ const struct btf_kind_operations * elem_ops ;
1335
+ const struct btf_type * elem_type ;
1336
+ u32 i , elem_size , elem_type_id ;
1337
+
1338
+ elem_type_id = array -> type ;
1339
+ elem_type = btf_type_id_size (btf , & elem_type_id , & elem_size );
1340
+ elem_ops = btf_type_ops (elem_type );
1341
+ seq_puts (m , "[" );
1342
+ for (i = 0 ; i < array -> nelems ; i ++ ) {
1343
+ if (i )
1344
+ seq_puts (m , "," );
1345
+
1346
+ elem_ops -> seq_show (btf , elem_type , elem_type_id , data ,
1347
+ bits_offset , m );
1348
+ data += elem_size ;
1349
+ }
1350
+ seq_puts (m , "]" );
1351
+ }
1352
+
1212
1353
static struct btf_kind_operations array_ops = {
1213
1354
.check_meta = btf_array_check_meta ,
1214
1355
.resolve = btf_array_resolve ,
1215
1356
.check_member = btf_array_check_member ,
1216
1357
.log_details = btf_array_log ,
1358
+ .seq_show = btf_array_seq_show ,
1217
1359
};
1218
1360
1219
1361
static int btf_struct_check_member (struct btf_verifier_env * env ,
@@ -1361,11 +1503,39 @@ static void btf_struct_log(struct btf_verifier_env *env,
1361
1503
btf_verifier_log (env , "size=%u vlen=%u" , t -> size , btf_type_vlen (t ));
1362
1504
}
1363
1505
1506
+ static void btf_struct_seq_show (const struct btf * btf , const struct btf_type * t ,
1507
+ u32 type_id , void * data , u8 bits_offset ,
1508
+ struct seq_file * m )
1509
+ {
1510
+ const char * seq = BTF_INFO_KIND (t -> info ) == BTF_KIND_UNION ? "|" : "," ;
1511
+ const struct btf_member * member ;
1512
+ u32 i ;
1513
+
1514
+ seq_puts (m , "{" );
1515
+ for_each_member (i , t , member ) {
1516
+ const struct btf_type * member_type = btf_type_by_id (btf ,
1517
+ member -> type );
1518
+ u32 member_offset = member -> offset ;
1519
+ u32 bytes_offset = BITS_ROUNDDOWN_BYTES (member_offset );
1520
+ u8 bits8_offset = BITS_PER_BYTE_MASKED (member_offset );
1521
+ const struct btf_kind_operations * ops ;
1522
+
1523
+ if (i )
1524
+ seq_puts (m , seq );
1525
+
1526
+ ops = btf_type_ops (member_type );
1527
+ ops -> seq_show (btf , member_type , member -> type ,
1528
+ data + bytes_offset , bits8_offset , m );
1529
+ }
1530
+ seq_puts (m , "}" );
1531
+ }
1532
+
1364
1533
static struct btf_kind_operations struct_ops = {
1365
1534
.check_meta = btf_struct_check_meta ,
1366
1535
.resolve = btf_struct_resolve ,
1367
1536
.check_member = btf_struct_check_member ,
1368
1537
.log_details = btf_struct_log ,
1538
+ .seq_show = btf_struct_seq_show ,
1369
1539
};
1370
1540
1371
1541
static int btf_enum_check_member (struct btf_verifier_env * env ,
@@ -1441,11 +1611,31 @@ static void btf_enum_log(struct btf_verifier_env *env,
1441
1611
btf_verifier_log (env , "size=%u vlen=%u" , t -> size , btf_type_vlen (t ));
1442
1612
}
1443
1613
1614
+ static void btf_enum_seq_show (const struct btf * btf , const struct btf_type * t ,
1615
+ u32 type_id , void * data , u8 bits_offset ,
1616
+ struct seq_file * m )
1617
+ {
1618
+ const struct btf_enum * enums = btf_type_enum (t );
1619
+ u32 i , nr_enums = btf_type_vlen (t );
1620
+ int v = * (int * )data ;
1621
+
1622
+ for (i = 0 ; i < nr_enums ; i ++ ) {
1623
+ if (v == enums [i ].val ) {
1624
+ seq_printf (m , "%s" ,
1625
+ btf_name_by_offset (btf , enums [i ].name ));
1626
+ return ;
1627
+ }
1628
+ }
1629
+
1630
+ seq_printf (m , "%d" , v );
1631
+ }
1632
+
1444
1633
static struct btf_kind_operations enum_ops = {
1445
1634
.check_meta = btf_enum_check_meta ,
1446
1635
.resolve = btf_df_resolve ,
1447
1636
.check_member = btf_enum_check_member ,
1448
1637
.log_details = btf_enum_log ,
1638
+ .seq_show = btf_enum_seq_show ,
1449
1639
};
1450
1640
1451
1641
static const struct btf_kind_operations * const kind_ops [NR_BTF_KINDS ] = {
@@ -1782,3 +1972,11 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
1782
1972
btf_free (btf );
1783
1973
return ERR_PTR (err );
1784
1974
}
1975
+
1976
+ void btf_type_seq_show (const struct btf * btf , u32 type_id , void * obj ,
1977
+ struct seq_file * m )
1978
+ {
1979
+ const struct btf_type * t = btf_type_by_id (btf , type_id );
1980
+
1981
+ btf_type_ops (t )-> seq_show (btf , t , type_id , obj , 0 , m );
1982
+ }
0 commit comments