@@ -174,12 +174,19 @@ struct bpf_program {
174174 char * name ;
175175 char * section_name ;
176176 struct bpf_insn * insns ;
177- size_t insns_cnt ;
177+ size_t insns_cnt , main_prog_cnt ;
178178 enum bpf_prog_type type ;
179179
180- struct {
180+ struct reloc_desc {
181+ enum {
182+ RELO_LD64 ,
183+ RELO_CALL ,
184+ } type ;
181185 int insn_idx ;
182- int map_idx ;
186+ union {
187+ int map_idx ;
188+ int text_off ;
189+ };
183190 } * reloc_desc ;
184191 int nr_reloc ;
185192
@@ -234,6 +241,7 @@ struct bpf_object {
234241 } * reloc ;
235242 int nr_reloc ;
236243 int maps_shndx ;
244+ int text_shndx ;
237245 } efile ;
238246 /*
239247 * All loaded bpf_object is linked in a list, which is
@@ -375,9 +383,13 @@ bpf_object__init_prog_names(struct bpf_object *obj)
375383 size_t pi , si ;
376384
377385 for (pi = 0 ; pi < obj -> nr_programs ; pi ++ ) {
378- char * name = NULL ;
386+ const char * name = NULL ;
379387
380388 prog = & obj -> programs [pi ];
389+ if (prog -> idx == obj -> efile .text_shndx ) {
390+ name = ".text" ;
391+ goto skip_search ;
392+ }
381393
382394 for (si = 0 ; si < symbols -> d_size / sizeof (GElf_Sym ) && !name ;
383395 si ++ ) {
@@ -405,7 +417,7 @@ bpf_object__init_prog_names(struct bpf_object *obj)
405417 prog -> section_name );
406418 return - EINVAL ;
407419 }
408-
420+ skip_search :
409421 prog -> name = strdup (name );
410422 if (!prog -> name ) {
411423 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)
795807 } else if ((sh .sh_type == SHT_PROGBITS ) &&
796808 (sh .sh_flags & SHF_EXECINSTR ) &&
797809 (data -> d_size > 0 )) {
810+ if (strcmp (name , ".text" ) == 0 )
811+ obj -> efile .text_shndx = idx ;
798812 err = bpf_object__add_program (obj , data -> d_buf ,
799813 data -> d_size , name , idx );
800814 if (err ) {
@@ -856,11 +870,14 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
856870}
857871
858872static 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 )
863875{
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 ;
864881 int i , nrels ;
865882
866883 pr_debug ("collecting relocating info for: '%s'\n" ,
@@ -893,8 +910,10 @@ bpf_program__collect_reloc(struct bpf_program *prog,
893910 GELF_R_SYM (rel .r_info ));
894911 return - LIBBPF_ERRNO__FORMAT ;
895912 }
913+ pr_debug ("relo for %ld value %ld name %d\n" ,
914+ rel .r_info >> 32 , sym .st_value , sym .st_name );
896915
897- if (sym .st_shndx != maps_shndx ) {
916+ if (sym .st_shndx != maps_shndx && sym . st_shndx != text_shndx ) {
898917 pr_warning ("Program '%s' contains non-map related relo data pointing to section %u\n" ,
899918 prog -> section_name , sym .st_shndx );
900919 return - LIBBPF_ERRNO__RELOC ;
@@ -903,6 +922,17 @@ bpf_program__collect_reloc(struct bpf_program *prog,
903922 insn_idx = rel .r_offset / sizeof (struct bpf_insn );
904923 pr_debug ("relocation: insn_idx=%u\n" , insn_idx );
905924
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+
906936 if (insns [insn_idx ].code != (BPF_LD | BPF_IMM | BPF_DW )) {
907937 pr_warning ("bpf: relocation: invalid relo for insns[%d].code 0x%x\n" ,
908938 insn_idx , insns [insn_idx ].code );
@@ -924,6 +954,7 @@ bpf_program__collect_reloc(struct bpf_program *prog,
924954 return - LIBBPF_ERRNO__RELOC ;
925955 }
926956
957+ prog -> reloc_desc [i ].type = RELO_LD64 ;
927958 prog -> reloc_desc [i ].insn_idx = insn_idx ;
928959 prog -> reloc_desc [i ].map_idx = map_idx ;
929960 }
@@ -962,28 +993,77 @@ bpf_object__create_maps(struct bpf_object *obj)
962993 return 0 ;
963994}
964995
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+
9651038static int
9661039bpf_program__relocate (struct bpf_program * prog , struct bpf_object * obj )
9671040{
968- int i ;
1041+ int i , err ;
9691042
9701043 if (!prog || !prog -> reloc_desc )
9711044 return 0 ;
9721045
9731046 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 ;
9761050
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 ;
9791053
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 ;
9841066 }
985- insns [insn_idx ].src_reg = BPF_PSEUDO_MAP_FD ;
986- insns [insn_idx ].imm = obj -> maps [map_idx ].fd ;
9871067 }
9881068
9891069 zfree (& prog -> reloc_desc );
@@ -1026,7 +1106,6 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
10261106 Elf_Data * data = obj -> efile .reloc [i ].data ;
10271107 int idx = shdr -> sh_info ;
10281108 struct bpf_program * prog ;
1029- size_t nr_maps = obj -> nr_maps ;
10301109
10311110 if (shdr -> sh_type != SHT_REL ) {
10321111 pr_warning ("internal error at %d\n" , __LINE__ );
@@ -1040,11 +1119,9 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
10401119 return - LIBBPF_ERRNO__RELOC ;
10411120 }
10421121
1043- err = bpf_program__collect_reloc (prog , nr_maps ,
1122+ err = bpf_program__collect_reloc (prog ,
10441123 shdr , data ,
1045- obj -> efile .symbols ,
1046- obj -> efile .maps_shndx ,
1047- obj -> maps );
1124+ obj );
10481125 if (err )
10491126 return err ;
10501127 }
@@ -1197,6 +1274,8 @@ bpf_object__load_progs(struct bpf_object *obj)
11971274 int err ;
11981275
11991276 for (i = 0 ; i < obj -> nr_programs ; i ++ ) {
1277+ if (obj -> programs [i ].idx == obj -> efile .text_shndx )
1278+ continue ;
12001279 err = bpf_program__load (& obj -> programs [i ],
12011280 obj -> license ,
12021281 obj -> kern_version );
@@ -1859,40 +1938,45 @@ long libbpf_get_error(const void *ptr)
18591938int bpf_prog_load (const char * file , enum bpf_prog_type type ,
18601939 struct bpf_object * * pobj , int * prog_fd )
18611940{
1862- struct bpf_program * prog ;
1941+ struct bpf_program * prog , * first_prog = NULL ;
18631942 struct bpf_object * obj ;
18641943 int err ;
18651944
18661945 obj = bpf_object__open (file );
18671946 if (IS_ERR (obj ))
18681947 return - ENOENT ;
18691948
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+ */
18821954 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+ }
18851960 }
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 ;
18861971 }
18871972
1888- bpf_program__set_type (prog , type );
18891973 err = bpf_object__load (obj );
18901974 if (err ) {
18911975 bpf_object__close (obj );
18921976 return - EINVAL ;
18931977 }
18941978
18951979 * pobj = obj ;
1896- * prog_fd = bpf_program__fd (prog );
1980+ * prog_fd = bpf_program__fd (first_prog );
18971981 return 0 ;
18981982}
0 commit comments