@@ -174,12 +174,19 @@ struct bpf_program {
174
174
char * name ;
175
175
char * section_name ;
176
176
struct bpf_insn * insns ;
177
- size_t insns_cnt ;
177
+ size_t insns_cnt , main_prog_cnt ;
178
178
enum bpf_prog_type type ;
179
179
180
- struct {
180
+ struct reloc_desc {
181
+ enum {
182
+ RELO_LD64 ,
183
+ RELO_CALL ,
184
+ } type ;
181
185
int insn_idx ;
182
- int map_idx ;
186
+ union {
187
+ int map_idx ;
188
+ int text_off ;
189
+ };
183
190
} * reloc_desc ;
184
191
int nr_reloc ;
185
192
@@ -234,6 +241,7 @@ struct bpf_object {
234
241
} * reloc ;
235
242
int nr_reloc ;
236
243
int maps_shndx ;
244
+ int text_shndx ;
237
245
} efile ;
238
246
/*
239
247
* All loaded bpf_object is linked in a list, which is
@@ -375,9 +383,13 @@ bpf_object__init_prog_names(struct bpf_object *obj)
375
383
size_t pi , si ;
376
384
377
385
for (pi = 0 ; pi < obj -> nr_programs ; pi ++ ) {
378
- char * name = NULL ;
386
+ const char * name = NULL ;
379
387
380
388
prog = & obj -> programs [pi ];
389
+ if (prog -> idx == obj -> efile .text_shndx ) {
390
+ name = ".text" ;
391
+ goto skip_search ;
392
+ }
381
393
382
394
for (si = 0 ; si < symbols -> d_size / sizeof (GElf_Sym ) && !name ;
383
395
si ++ ) {
@@ -405,7 +417,7 @@ bpf_object__init_prog_names(struct bpf_object *obj)
405
417
prog -> section_name );
406
418
return - EINVAL ;
407
419
}
408
-
420
+ skip_search :
409
421
prog -> name = strdup (name );
410
422
if (!prog -> name ) {
411
423
pr_warning ("failed to allocate memory for prog sym %s\n" ,
@@ -795,6 +807,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
795
807
} else if ((sh .sh_type == SHT_PROGBITS ) &&
796
808
(sh .sh_flags & SHF_EXECINSTR ) &&
797
809
(data -> d_size > 0 )) {
810
+ if (strcmp (name , ".text" ) == 0 )
811
+ obj -> efile .text_shndx = idx ;
798
812
err = bpf_object__add_program (obj , data -> d_buf ,
799
813
data -> d_size , name , idx );
800
814
if (err ) {
@@ -856,11 +870,14 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
856
870
}
857
871
858
872
static int
859
- bpf_program__collect_reloc (struct bpf_program * prog ,
860
- size_t nr_maps , GElf_Shdr * shdr ,
861
- Elf_Data * data , Elf_Data * symbols ,
862
- int maps_shndx , struct bpf_map * maps )
873
+ bpf_program__collect_reloc (struct bpf_program * prog , GElf_Shdr * shdr ,
874
+ Elf_Data * data , struct bpf_object * obj )
863
875
{
876
+ Elf_Data * symbols = obj -> efile .symbols ;
877
+ int text_shndx = obj -> efile .text_shndx ;
878
+ int maps_shndx = obj -> efile .maps_shndx ;
879
+ struct bpf_map * maps = obj -> maps ;
880
+ size_t nr_maps = obj -> nr_maps ;
864
881
int i , nrels ;
865
882
866
883
pr_debug ("collecting relocating info for: '%s'\n" ,
@@ -893,8 +910,10 @@ bpf_program__collect_reloc(struct bpf_program *prog,
893
910
GELF_R_SYM (rel .r_info ));
894
911
return - LIBBPF_ERRNO__FORMAT ;
895
912
}
913
+ pr_debug ("relo for %ld value %ld name %d\n" ,
914
+ rel .r_info >> 32 , sym .st_value , sym .st_name );
896
915
897
- if (sym .st_shndx != maps_shndx ) {
916
+ if (sym .st_shndx != maps_shndx && sym . st_shndx != text_shndx ) {
898
917
pr_warning ("Program '%s' contains non-map related relo data pointing to section %u\n" ,
899
918
prog -> section_name , sym .st_shndx );
900
919
return - LIBBPF_ERRNO__RELOC ;
@@ -903,6 +922,17 @@ bpf_program__collect_reloc(struct bpf_program *prog,
903
922
insn_idx = rel .r_offset / sizeof (struct bpf_insn );
904
923
pr_debug ("relocation: insn_idx=%u\n" , insn_idx );
905
924
925
+ if (insns [insn_idx ].code == (BPF_JMP | BPF_CALL )) {
926
+ if (insns [insn_idx ].src_reg != BPF_PSEUDO_CALL ) {
927
+ pr_warning ("incorrect bpf_call opcode\n" );
928
+ return - LIBBPF_ERRNO__RELOC ;
929
+ }
930
+ prog -> reloc_desc [i ].type = RELO_CALL ;
931
+ prog -> reloc_desc [i ].insn_idx = insn_idx ;
932
+ prog -> reloc_desc [i ].text_off = sym .st_value ;
933
+ continue ;
934
+ }
935
+
906
936
if (insns [insn_idx ].code != (BPF_LD | BPF_IMM | BPF_DW )) {
907
937
pr_warning ("bpf: relocation: invalid relo for insns[%d].code 0x%x\n" ,
908
938
insn_idx , insns [insn_idx ].code );
@@ -924,6 +954,7 @@ bpf_program__collect_reloc(struct bpf_program *prog,
924
954
return - LIBBPF_ERRNO__RELOC ;
925
955
}
926
956
957
+ prog -> reloc_desc [i ].type = RELO_LD64 ;
927
958
prog -> reloc_desc [i ].insn_idx = insn_idx ;
928
959
prog -> reloc_desc [i ].map_idx = map_idx ;
929
960
}
@@ -962,28 +993,77 @@ bpf_object__create_maps(struct bpf_object *obj)
962
993
return 0 ;
963
994
}
964
995
996
+ static int
997
+ bpf_program__reloc_text (struct bpf_program * prog , struct bpf_object * obj ,
998
+ struct reloc_desc * relo )
999
+ {
1000
+ struct bpf_insn * insn , * new_insn ;
1001
+ struct bpf_program * text ;
1002
+ size_t new_cnt ;
1003
+
1004
+ if (relo -> type != RELO_CALL )
1005
+ return - LIBBPF_ERRNO__RELOC ;
1006
+
1007
+ if (prog -> idx == obj -> efile .text_shndx ) {
1008
+ pr_warning ("relo in .text insn %d into off %d\n" ,
1009
+ relo -> insn_idx , relo -> text_off );
1010
+ return - LIBBPF_ERRNO__RELOC ;
1011
+ }
1012
+
1013
+ if (prog -> main_prog_cnt == 0 ) {
1014
+ text = bpf_object__find_prog_by_idx (obj , obj -> efile .text_shndx );
1015
+ if (!text ) {
1016
+ pr_warning ("no .text section found yet relo into text exist\n" );
1017
+ return - LIBBPF_ERRNO__RELOC ;
1018
+ }
1019
+ new_cnt = prog -> insns_cnt + text -> insns_cnt ;
1020
+ new_insn = realloc (prog -> insns , new_cnt * sizeof (* insn ));
1021
+ if (!new_insn ) {
1022
+ pr_warning ("oom in prog realloc\n" );
1023
+ return - ENOMEM ;
1024
+ }
1025
+ memcpy (new_insn + prog -> insns_cnt , text -> insns ,
1026
+ text -> insns_cnt * sizeof (* insn ));
1027
+ prog -> insns = new_insn ;
1028
+ prog -> main_prog_cnt = prog -> insns_cnt ;
1029
+ prog -> insns_cnt = new_cnt ;
1030
+ }
1031
+ insn = & prog -> insns [relo -> insn_idx ];
1032
+ insn -> imm += prog -> main_prog_cnt - relo -> insn_idx ;
1033
+ pr_debug ("added %zd insn from %s to prog %s\n" ,
1034
+ text -> insns_cnt , text -> section_name , prog -> section_name );
1035
+ return 0 ;
1036
+ }
1037
+
965
1038
static int
966
1039
bpf_program__relocate (struct bpf_program * prog , struct bpf_object * obj )
967
1040
{
968
- int i ;
1041
+ int i , err ;
969
1042
970
1043
if (!prog || !prog -> reloc_desc )
971
1044
return 0 ;
972
1045
973
1046
for (i = 0 ; i < prog -> nr_reloc ; i ++ ) {
974
- int insn_idx , map_idx ;
975
- struct bpf_insn * insns = prog -> insns ;
1047
+ if (prog -> reloc_desc [i ].type == RELO_LD64 ) {
1048
+ struct bpf_insn * insns = prog -> insns ;
1049
+ int insn_idx , map_idx ;
976
1050
977
- insn_idx = prog -> reloc_desc [i ].insn_idx ;
978
- map_idx = prog -> reloc_desc [i ].map_idx ;
1051
+ insn_idx = prog -> reloc_desc [i ].insn_idx ;
1052
+ map_idx = prog -> reloc_desc [i ].map_idx ;
979
1053
980
- if (insn_idx >= (int )prog -> insns_cnt ) {
981
- pr_warning ("relocation out of range: '%s'\n" ,
982
- prog -> section_name );
983
- return - LIBBPF_ERRNO__RELOC ;
1054
+ if (insn_idx >= (int )prog -> insns_cnt ) {
1055
+ pr_warning ("relocation out of range: '%s'\n" ,
1056
+ prog -> section_name );
1057
+ return - LIBBPF_ERRNO__RELOC ;
1058
+ }
1059
+ insns [insn_idx ].src_reg = BPF_PSEUDO_MAP_FD ;
1060
+ insns [insn_idx ].imm = obj -> maps [map_idx ].fd ;
1061
+ } else {
1062
+ err = bpf_program__reloc_text (prog , obj ,
1063
+ & prog -> reloc_desc [i ]);
1064
+ if (err )
1065
+ return err ;
984
1066
}
985
- insns [insn_idx ].src_reg = BPF_PSEUDO_MAP_FD ;
986
- insns [insn_idx ].imm = obj -> maps [map_idx ].fd ;
987
1067
}
988
1068
989
1069
zfree (& prog -> reloc_desc );
@@ -1026,7 +1106,6 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1026
1106
Elf_Data * data = obj -> efile .reloc [i ].data ;
1027
1107
int idx = shdr -> sh_info ;
1028
1108
struct bpf_program * prog ;
1029
- size_t nr_maps = obj -> nr_maps ;
1030
1109
1031
1110
if (shdr -> sh_type != SHT_REL ) {
1032
1111
pr_warning ("internal error at %d\n" , __LINE__ );
@@ -1040,11 +1119,9 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1040
1119
return - LIBBPF_ERRNO__RELOC ;
1041
1120
}
1042
1121
1043
- err = bpf_program__collect_reloc (prog , nr_maps ,
1122
+ err = bpf_program__collect_reloc (prog ,
1044
1123
shdr , data ,
1045
- obj -> efile .symbols ,
1046
- obj -> efile .maps_shndx ,
1047
- obj -> maps );
1124
+ obj );
1048
1125
if (err )
1049
1126
return err ;
1050
1127
}
@@ -1197,6 +1274,8 @@ bpf_object__load_progs(struct bpf_object *obj)
1197
1274
int err ;
1198
1275
1199
1276
for (i = 0 ; i < obj -> nr_programs ; i ++ ) {
1277
+ if (obj -> programs [i ].idx == obj -> efile .text_shndx )
1278
+ continue ;
1200
1279
err = bpf_program__load (& obj -> programs [i ],
1201
1280
obj -> license ,
1202
1281
obj -> kern_version );
@@ -1859,40 +1938,45 @@ long libbpf_get_error(const void *ptr)
1859
1938
int bpf_prog_load (const char * file , enum bpf_prog_type type ,
1860
1939
struct bpf_object * * pobj , int * prog_fd )
1861
1940
{
1862
- struct bpf_program * prog ;
1941
+ struct bpf_program * prog , * first_prog = NULL ;
1863
1942
struct bpf_object * obj ;
1864
1943
int err ;
1865
1944
1866
1945
obj = bpf_object__open (file );
1867
1946
if (IS_ERR (obj ))
1868
1947
return - ENOENT ;
1869
1948
1870
- prog = bpf_program__next (NULL , obj );
1871
- if (!prog ) {
1872
- bpf_object__close (obj );
1873
- return - ENOENT ;
1874
- }
1875
-
1876
- /*
1877
- * If type is not specified, try to guess it based on
1878
- * section name.
1879
- */
1880
- if (type == BPF_PROG_TYPE_UNSPEC ) {
1881
- type = bpf_program__guess_type (prog );
1949
+ bpf_object__for_each_program (prog , obj ) {
1950
+ /*
1951
+ * If type is not specified, try to guess it based on
1952
+ * section name.
1953
+ */
1882
1954
if (type == BPF_PROG_TYPE_UNSPEC ) {
1883
- bpf_object__close (obj );
1884
- return - EINVAL ;
1955
+ type = bpf_program__guess_type (prog );
1956
+ if (type == BPF_PROG_TYPE_UNSPEC ) {
1957
+ bpf_object__close (obj );
1958
+ return - EINVAL ;
1959
+ }
1885
1960
}
1961
+
1962
+ bpf_program__set_type (prog , type );
1963
+ if (prog -> idx != obj -> efile .text_shndx && !first_prog )
1964
+ first_prog = prog ;
1965
+ }
1966
+
1967
+ if (!first_prog ) {
1968
+ pr_warning ("object file doesn't contain bpf program\n" );
1969
+ bpf_object__close (obj );
1970
+ return - ENOENT ;
1886
1971
}
1887
1972
1888
- bpf_program__set_type (prog , type );
1889
1973
err = bpf_object__load (obj );
1890
1974
if (err ) {
1891
1975
bpf_object__close (obj );
1892
1976
return - EINVAL ;
1893
1977
}
1894
1978
1895
1979
* pobj = obj ;
1896
- * prog_fd = bpf_program__fd (prog );
1980
+ * prog_fd = bpf_program__fd (first_prog );
1897
1981
return 0 ;
1898
1982
}
0 commit comments