[BPF] Add BTF Var and DataSec Support
Two new kinds, BTF_KIND_VAR and BTF_KIND_DATASEC, are added.
BTF_KIND_VAR has the following specification:
btf_type.name: var name
btf_type.info: type kind
btf_type.type: var type
// btf_type is followed by one u32
u32: varinfo (currently, only 0 - static, 1 - global allocated in elf sections)
Not all globals are supported in this patch. The following globals are supported:
. static variables with or without section attributes
. global variables with section attributes
The inclusion of globals with section attributes
is for future potential extraction of key/value
type id's from map definition.
BTF_KIND_DATASEC has the following specification:
btf_type.name: section name associated with variable or
one of .data/.bss/.readonly
btf_type.info: type kind and vlen for # of variables
btf_type.size: 0
#vlen number of the following:
u32: id of corresponding BTF_KIND_VAR
u32: in-session offset of the var
u32: the size of memory var occupied
At the time of debug info emission, the data section
size is unknown, so the btf_type.size = 0 for
BTF_KIND_DATASEC. The loader can patch it during
loading time.
The in-session offseet of the var is only available
for static variables. For global variables, the
loader neeeds to assign the global variable symbol value in
symbol table to in-section offset.
The size of memory is used to specify the amount of the
memory a variable occupies. Typically, it equals to
the type size, but for certain structures, e.g.,
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
The static variable s2 has size of 20.
Note that for BTF_KIND_DATASEC name, the section name
does not contain object name. The compiler does have
input module name. For example, two cases below:
. clang -target bpf -O2 -g -c test.c
The compiler knows the input file (module) is test.c
and can generate sec name like test.data/test.bss etc.
. clang -target bpf -O2 -g -emit-llvm -c test.c -o - |
llc -march=bpf -filetype=obj -o test.o
The llc compiler has the input file as stdin, and
would generate something like stdin.data/stdin.bss etc.
which does not really make sense.
For any user specificed section name, e.g.,
static volatile int a __attribute__((section("id1")));
static volatile const int b __attribute__((section("id2")));
The DataSec with name "id1" and "id2" does not contain
information whether the section is readonly or not.
The loader needs to check the corresponding elf section
flags for such information.
A simple example:
-bash-4.4$ cat t.c
int g1;
int g2 = 3;
const int g3 = 4;
static volatile int s1;
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
static volatile const int s3 = 4;
int m __attribute__((section("maps"), used)) = 4;
int test() { return g1 + g2 + g3 + s1 + s2.a + s3 + m; }
-bash-4.4$ clang -target bpf -O2 -g -S t.c
Checking t.s, 4 BTF_KIND_VAR's are generated (s1, s2, s3 and m).
4 BTF_KIND_DATASEC's are generated with names
".data", ".bss", ".rodata" and "maps".
Signed-off-by: Yonghong Song <yhs@fb.com>
Differential Revision: https://reviews.llvm.org/D59441
llvm-svn: 356326
2019-03-16 23:36:31 +08:00
; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
; Source code:
; static volatile const char __attribute__((section("maps"))) a;
; int foo() {
; static volatile const short b __attribute__((section("maps"))) = 3;
; return a + b;
; }
; Compilation flag:
; clang -target bpf -O2 -g -S -emit-llvm test.c
@foo.b = internal constant i16 3 , section "maps" , align 2 , !dbg !0
@a = internal constant i8 0 , section "maps" , align 1 , !dbg !10
; Function Attrs: norecurse nounwind
define d s o _ l o c a l i32 @foo ( ) local_unnamed_addr #0 !dbg !2 {
%1 = load volatile i8 , i8 * @a , align 1 , !dbg !22 , !tbaa !23
%2 = sext i8 %1 to i32 , !dbg !22
%3 = load volatile i16 , i16 * @foo.b , align 2 , !dbg !26 , !tbaa !27
%4 = sext i16 %3 to i32 , !dbg !26
%5 = add nsw i32 %4 , %2 , !dbg !29
ret i32 %5 , !dbg !30
}
; CHECK: .section .BTF,"",@progbits
; CHECK-NEXT: .short 60319 # 0xeb9f
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .long 24
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long 188
; CHECK-NEXT: .long 188
; CHECK-NEXT: .long 76
; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1)
; CHECK-NEXT: .long 218103808 # 0xd000000
; CHECK-NEXT: .long 2
; CHECK-NEXT: .long 44 # BTF_KIND_INT(id = 2)
; CHECK-NEXT: .long 16777216 # 0x1000000
; CHECK-NEXT: .long 4
; CHECK-NEXT: .long 16777248 # 0x1000020
; CHECK-NEXT: .long 48 # BTF_KIND_FUNC(id = 3)
; CHECK-NEXT: .long 201326592 # 0xc000000
; CHECK-NEXT: .long 1
; CHECK-NEXT: .long 0 # BTF_KIND_CONST(id = 4)
; CHECK-NEXT: .long 167772160 # 0xa000000
; CHECK-NEXT: .long 5
; CHECK-NEXT: .long 0 # BTF_KIND_VOLATILE(id = 5)
; CHECK-NEXT: .long 150994944 # 0x9000000
; CHECK-NEXT: .long 6
; CHECK-NEXT: .long 52 # BTF_KIND_INT(id = 6)
; CHECK-NEXT: .long 16777216 # 0x1000000
; CHECK-NEXT: .long 2
; CHECK-NEXT: .long 16777232 # 0x1000010
; CHECK-NEXT: .long 58 # BTF_KIND_VAR(id = 7)
; CHECK-NEXT: .long 234881024 # 0xe000000
2019-03-22 09:30:50 +08:00
; CHECK-NEXT: .long 4
[BPF] Add BTF Var and DataSec Support
Two new kinds, BTF_KIND_VAR and BTF_KIND_DATASEC, are added.
BTF_KIND_VAR has the following specification:
btf_type.name: var name
btf_type.info: type kind
btf_type.type: var type
// btf_type is followed by one u32
u32: varinfo (currently, only 0 - static, 1 - global allocated in elf sections)
Not all globals are supported in this patch. The following globals are supported:
. static variables with or without section attributes
. global variables with section attributes
The inclusion of globals with section attributes
is for future potential extraction of key/value
type id's from map definition.
BTF_KIND_DATASEC has the following specification:
btf_type.name: section name associated with variable or
one of .data/.bss/.readonly
btf_type.info: type kind and vlen for # of variables
btf_type.size: 0
#vlen number of the following:
u32: id of corresponding BTF_KIND_VAR
u32: in-session offset of the var
u32: the size of memory var occupied
At the time of debug info emission, the data section
size is unknown, so the btf_type.size = 0 for
BTF_KIND_DATASEC. The loader can patch it during
loading time.
The in-session offseet of the var is only available
for static variables. For global variables, the
loader neeeds to assign the global variable symbol value in
symbol table to in-section offset.
The size of memory is used to specify the amount of the
memory a variable occupies. Typically, it equals to
the type size, but for certain structures, e.g.,
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
The static variable s2 has size of 20.
Note that for BTF_KIND_DATASEC name, the section name
does not contain object name. The compiler does have
input module name. For example, two cases below:
. clang -target bpf -O2 -g -c test.c
The compiler knows the input file (module) is test.c
and can generate sec name like test.data/test.bss etc.
. clang -target bpf -O2 -g -emit-llvm -c test.c -o - |
llc -march=bpf -filetype=obj -o test.o
The llc compiler has the input file as stdin, and
would generate something like stdin.data/stdin.bss etc.
which does not really make sense.
For any user specificed section name, e.g.,
static volatile int a __attribute__((section("id1")));
static volatile const int b __attribute__((section("id2")));
The DataSec with name "id1" and "id2" does not contain
information whether the section is readonly or not.
The loader needs to check the corresponding elf section
flags for such information.
A simple example:
-bash-4.4$ cat t.c
int g1;
int g2 = 3;
const int g3 = 4;
static volatile int s1;
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
static volatile const int s3 = 4;
int m __attribute__((section("maps"), used)) = 4;
int test() { return g1 + g2 + g3 + s1 + s2.a + s3 + m; }
-bash-4.4$ clang -target bpf -O2 -g -S t.c
Checking t.s, 4 BTF_KIND_VAR's are generated (s1, s2, s3 and m).
4 BTF_KIND_DATASEC's are generated with names
".data", ".bss", ".rodata" and "maps".
Signed-off-by: Yonghong Song <yhs@fb.com>
Differential Revision: https://reviews.llvm.org/D59441
llvm-svn: 356326
2019-03-16 23:36:31 +08:00
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long 0 # BTF_KIND_CONST(id = 8)
; CHECK-NEXT: .long 167772160 # 0xa000000
; CHECK-NEXT: .long 9
; CHECK-NEXT: .long 0 # BTF_KIND_VOLATILE(id = 9)
; CHECK-NEXT: .long 150994944 # 0x9000000
; CHECK-NEXT: .long 10
; CHECK-NEXT: .long 64 # BTF_KIND_INT(id = 10)
; CHECK-NEXT: .long 16777216 # 0x1000000
; CHECK-NEXT: .long 1
; CHECK-NEXT: .long 16777224 # 0x1000008
; CHECK-NEXT: .long 69 # BTF_KIND_VAR(id = 11)
; CHECK-NEXT: .long 234881024 # 0xe000000
2019-03-22 09:30:50 +08:00
; CHECK-NEXT: .long 8
[BPF] Add BTF Var and DataSec Support
Two new kinds, BTF_KIND_VAR and BTF_KIND_DATASEC, are added.
BTF_KIND_VAR has the following specification:
btf_type.name: var name
btf_type.info: type kind
btf_type.type: var type
// btf_type is followed by one u32
u32: varinfo (currently, only 0 - static, 1 - global allocated in elf sections)
Not all globals are supported in this patch. The following globals are supported:
. static variables with or without section attributes
. global variables with section attributes
The inclusion of globals with section attributes
is for future potential extraction of key/value
type id's from map definition.
BTF_KIND_DATASEC has the following specification:
btf_type.name: section name associated with variable or
one of .data/.bss/.readonly
btf_type.info: type kind and vlen for # of variables
btf_type.size: 0
#vlen number of the following:
u32: id of corresponding BTF_KIND_VAR
u32: in-session offset of the var
u32: the size of memory var occupied
At the time of debug info emission, the data section
size is unknown, so the btf_type.size = 0 for
BTF_KIND_DATASEC. The loader can patch it during
loading time.
The in-session offseet of the var is only available
for static variables. For global variables, the
loader neeeds to assign the global variable symbol value in
symbol table to in-section offset.
The size of memory is used to specify the amount of the
memory a variable occupies. Typically, it equals to
the type size, but for certain structures, e.g.,
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
The static variable s2 has size of 20.
Note that for BTF_KIND_DATASEC name, the section name
does not contain object name. The compiler does have
input module name. For example, two cases below:
. clang -target bpf -O2 -g -c test.c
The compiler knows the input file (module) is test.c
and can generate sec name like test.data/test.bss etc.
. clang -target bpf -O2 -g -emit-llvm -c test.c -o - |
llc -march=bpf -filetype=obj -o test.o
The llc compiler has the input file as stdin, and
would generate something like stdin.data/stdin.bss etc.
which does not really make sense.
For any user specificed section name, e.g.,
static volatile int a __attribute__((section("id1")));
static volatile const int b __attribute__((section("id2")));
The DataSec with name "id1" and "id2" does not contain
information whether the section is readonly or not.
The loader needs to check the corresponding elf section
flags for such information.
A simple example:
-bash-4.4$ cat t.c
int g1;
int g2 = 3;
const int g3 = 4;
static volatile int s1;
struct tt {
int a;
int b;
char c[];
};
static volatile struct tt s2 = {3, 4, "abcdefghi"};
static volatile const int s3 = 4;
int m __attribute__((section("maps"), used)) = 4;
int test() { return g1 + g2 + g3 + s1 + s2.a + s3 + m; }
-bash-4.4$ clang -target bpf -O2 -g -S t.c
Checking t.s, 4 BTF_KIND_VAR's are generated (s1, s2, s3 and m).
4 BTF_KIND_DATASEC's are generated with names
".data", ".bss", ".rodata" and "maps".
Signed-off-by: Yonghong Song <yhs@fb.com>
Differential Revision: https://reviews.llvm.org/D59441
llvm-svn: 356326
2019-03-16 23:36:31 +08:00
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long 71 # BTF_KIND_DATASEC(id = 12)
; CHECK-NEXT: .long 251658242 # 0xf000002
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long 7
; CHECK-NEXT: .long foo.b
; CHECK-NEXT: .long 2
; CHECK-NEXT: .long 11
; CHECK-NEXT: .long a
; CHECK-NEXT: .long 1
; CHECK-NEXT: .byte 0 # string offset=0
; CHECK-NEXT: .ascii ".text" # string offset=1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "int" # string offset=44
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "foo" # string offset=48
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "short" # string offset=52
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "foo.b" # string offset=58
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "char" # string offset=64
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .byte 97 # string offset=69
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .ascii "maps" # string offset=71
; CHECK-NEXT: .byte 0
attributes #0 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math" = "false" "disable-tail-calls" = "false" "less-precise-fpmad" = "false" "no-frame-pointer-elim" = "true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math" = "false" "no-jump-tables" = "false" "no-nans-fp-math" = "false" "no-signed-zeros-fp-math" = "false" "no-trapping-math" = "false" "stack-protector-buffer-size" = "8" "unsafe-fp-math" = "false" "use-soft-float" = "false" }
!llvm.dbg.cu = ! { !7 }
!llvm.module.flags = ! { !18 , !19 , !20 }
!llvm.ident = ! { !21 }
!0 = !DIGlobalVariableExpression ( var: !1 , expr: !DIExpression ( ) )
!1 = distinct !DIGlobalVariable ( name: "b" , scope: !2 , file: !3 , line: 3 , type: !15 , isLocal: true , isDefinition: true )
!2 = distinct !DISubprogram ( name: "foo" , scope: !3 , file: !3 , line: 2 , type: !4 , isLocal: false , isDefinition: true , scopeLine: 2 , isOptimized: true , unit: !7 , retainedNodes: !8 )
!3 = !DIFile ( filename: "test.c" , directory: "/home/yhs/work/tests/llvm/bug" )
!4 = !DISubroutineType ( types: !5 )
!5 = ! { !6 }
!6 = !DIBasicType ( name: "int" , size: 32 , encoding: D W _ A T E _ s i g n e d )
!7 = distinct !DICompileUnit ( language: D W _ L A N G _ C 99 , file: !3 , producer: "clang version 8.0.20181009 " , isOptimized: true , runtimeVersion: 0 , emissionKind: F u l l D e b u g , enums: !8 , globals: !9 , nameTableKind: N one )
!8 = ! { }
!9 = ! { !0 , !10 }
!10 = !DIGlobalVariableExpression ( var: !11 , expr: !DIExpression ( ) )
!11 = distinct !DIGlobalVariable ( name: "a" , scope: !7 , file: !3 , line: 1 , type: !12 , isLocal: true , isDefinition: true )
!12 = !DIDerivedType ( tag: D W _ T A G _ c o n s t _ type , baseType: !13 )
!13 = !DIDerivedType ( tag: D W _ T A G _ v o l a t i l e _ type , baseType: !14 )
!14 = !DIBasicType ( name: "char" , size: 8 , encoding: D W _ A T E _ s i g n e d _ c h a r )
!15 = !DIDerivedType ( tag: D W _ T A G _ c o n s t _ type , baseType: !16 )
!16 = !DIDerivedType ( tag: D W _ T A G _ v o l a t i l e _ type , baseType: !17 )
!17 = !DIBasicType ( name: "short" , size: 16 , encoding: D W _ A T E _ s i g n e d )
!18 = ! { i32 2 , !"Dwarf Version" , i32 4 }
!19 = ! { i32 2 , !"Debug Info Version" , i32 3 }
!20 = ! { i32 1 , !"wchar_size" , i32 4 }
!21 = ! { !"clang version 8.0.20181009 " }
!22 = !DILocation ( line: 4 , column: 10 , scope: !2 )
!23 = ! { !24 , !24 , i64 0 }
!24 = ! { !"omnipotent char" , !25 , i64 0 }
!25 = ! { !"Simple C/C++ TBAA" }
!26 = !DILocation ( line: 4 , column: 14 , scope: !2 )
!27 = ! { !28 , !28 , i64 0 }
!28 = ! { !"short" , !24 , i64 0 }
!29 = !DILocation ( line: 4 , column: 12 , scope: !2 )
!30 = !DILocation ( line: 4 , column: 3 , scope: !2 )