@@ -276,8 +276,8 @@ struct bpf_object {
276
276
struct {
277
277
GElf_Shdr shdr ;
278
278
Elf_Data * data ;
279
- } * reloc ;
280
- int nr_reloc ;
279
+ } * reloc_sects ;
280
+ int nr_reloc_sects ;
281
281
int maps_shndx ;
282
282
int btf_maps_shndx ;
283
283
int text_shndx ;
@@ -575,8 +575,8 @@ static void bpf_object__elf_finish(struct bpf_object *obj)
575
575
obj -> efile .rodata = NULL ;
576
576
obj -> efile .bss = NULL ;
577
577
578
- zfree (& obj -> efile .reloc );
579
- obj -> efile .nr_reloc = 0 ;
578
+ zfree (& obj -> efile .reloc_sects );
579
+ obj -> efile .nr_reloc_sects = 0 ;
580
580
zclose (obj -> efile .fd );
581
581
obj -> efile .obj_buf = NULL ;
582
582
obj -> efile .obj_buf_sz = 0 ;
@@ -1693,8 +1693,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, bool relaxed_maps,
1693
1693
pr_debug ("skip section(%d) %s\n" , idx , name );
1694
1694
}
1695
1695
} else if (sh .sh_type == SHT_REL ) {
1696
- int nr_reloc = obj -> efile .nr_reloc ;
1697
- void * reloc = obj -> efile .reloc ;
1696
+ int nr_sects = obj -> efile .nr_reloc_sects ;
1697
+ void * sects = obj -> efile .reloc_sects ;
1698
1698
int sec = sh .sh_info ; /* points to other section */
1699
1699
1700
1700
/* Only do relo for section with exec instructions */
@@ -1704,18 +1704,18 @@ static int bpf_object__elf_collect(struct bpf_object *obj, bool relaxed_maps,
1704
1704
continue ;
1705
1705
}
1706
1706
1707
- reloc = reallocarray (reloc , nr_reloc + 1 ,
1708
- sizeof (* obj -> efile .reloc ));
1709
- if (!reloc ) {
1710
- pr_warn ("realloc failed\n" );
1707
+ sects = reallocarray (sects , nr_sects + 1 ,
1708
+ sizeof (* obj -> efile .reloc_sects ));
1709
+ if (!sects ) {
1710
+ pr_warn ("reloc_sects realloc failed\n" );
1711
1711
return - ENOMEM ;
1712
1712
}
1713
1713
1714
- obj -> efile .reloc = reloc ;
1715
- obj -> efile .nr_reloc ++ ;
1714
+ obj -> efile .reloc_sects = sects ;
1715
+ obj -> efile .nr_reloc_sects ++ ;
1716
1716
1717
- obj -> efile .reloc [ nr_reloc ].shdr = sh ;
1718
- obj -> efile .reloc [ nr_reloc ].data = data ;
1717
+ obj -> efile .reloc_sects [ nr_sects ].shdr = sh ;
1718
+ obj -> efile .reloc_sects [ nr_sects ].data = data ;
1719
1719
} else if (sh .sh_type == SHT_NOBITS && strcmp (name , ".bss" ) == 0 ) {
1720
1720
obj -> efile .bss = data ;
1721
1721
obj -> efile .bss_shndx = idx ;
@@ -1780,14 +1780,6 @@ static bool bpf_object__shndx_is_maps(const struct bpf_object *obj,
1780
1780
shndx == obj -> efile .btf_maps_shndx ;
1781
1781
}
1782
1782
1783
- static bool bpf_object__relo_in_known_section (const struct bpf_object * obj ,
1784
- int shndx )
1785
- {
1786
- return shndx == obj -> efile .text_shndx ||
1787
- bpf_object__shndx_is_maps (obj , shndx ) ||
1788
- bpf_object__shndx_is_data (obj , shndx );
1789
- }
1790
-
1791
1783
static enum libbpf_map_type
1792
1784
bpf_object__section_to_libbpf_map_type (const struct bpf_object * obj , int shndx )
1793
1785
{
@@ -1801,14 +1793,124 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx)
1801
1793
return LIBBPF_MAP_UNSPEC ;
1802
1794
}
1803
1795
1796
+ static int bpf_program__record_reloc (struct bpf_program * prog ,
1797
+ struct reloc_desc * reloc_desc ,
1798
+ __u32 insn_idx , const char * name ,
1799
+ const GElf_Sym * sym , const GElf_Rel * rel )
1800
+ {
1801
+ struct bpf_insn * insn = & prog -> insns [insn_idx ];
1802
+ size_t map_idx , nr_maps = prog -> obj -> nr_maps ;
1803
+ struct bpf_object * obj = prog -> obj ;
1804
+ __u32 shdr_idx = sym -> st_shndx ;
1805
+ enum libbpf_map_type type ;
1806
+ struct bpf_map * map ;
1807
+
1808
+ /* sub-program call relocation */
1809
+ if (insn -> code == (BPF_JMP | BPF_CALL )) {
1810
+ if (insn -> src_reg != BPF_PSEUDO_CALL ) {
1811
+ pr_warn ("incorrect bpf_call opcode\n" );
1812
+ return - LIBBPF_ERRNO__RELOC ;
1813
+ }
1814
+ /* text_shndx can be 0, if no default "main" program exists */
1815
+ if (!shdr_idx || shdr_idx != obj -> efile .text_shndx ) {
1816
+ pr_warn ("bad call relo against section %u\n" , shdr_idx );
1817
+ return - LIBBPF_ERRNO__RELOC ;
1818
+ }
1819
+ if (sym -> st_value % 8 ) {
1820
+ pr_warn ("bad call relo offset: %lu\n" , sym -> st_value );
1821
+ return - LIBBPF_ERRNO__RELOC ;
1822
+ }
1823
+ reloc_desc -> type = RELO_CALL ;
1824
+ reloc_desc -> insn_idx = insn_idx ;
1825
+ reloc_desc -> text_off = sym -> st_value / 8 ;
1826
+ obj -> has_pseudo_calls = true;
1827
+ return 0 ;
1828
+ }
1829
+
1830
+ if (insn -> code != (BPF_LD | BPF_IMM | BPF_DW )) {
1831
+ pr_warn ("bpf: relocation: invalid relo for insns[%d].code 0x%x\n" ,
1832
+ insn_idx , insn -> code );
1833
+ return - LIBBPF_ERRNO__RELOC ;
1834
+ }
1835
+ if (!shdr_idx || shdr_idx >= SHN_LORESERVE ) {
1836
+ pr_warn ("relocation: not yet supported relo for non-static global \'%s\' variable in special section (0x%x) found in insns[%d].code 0x%x\n" ,
1837
+ name , shdr_idx , insn_idx , insn -> code );
1838
+ return - LIBBPF_ERRNO__RELOC ;
1839
+ }
1840
+
1841
+ type = bpf_object__section_to_libbpf_map_type (obj , shdr_idx );
1842
+
1843
+ /* generic map reference relocation */
1844
+ if (type == LIBBPF_MAP_UNSPEC ) {
1845
+ if (!bpf_object__shndx_is_maps (obj , shdr_idx )) {
1846
+ pr_warn ("bad map relo against section %u\n" ,
1847
+ shdr_idx );
1848
+ return - LIBBPF_ERRNO__RELOC ;
1849
+ }
1850
+ for (map_idx = 0 ; map_idx < nr_maps ; map_idx ++ ) {
1851
+ map = & obj -> maps [map_idx ];
1852
+ if (map -> libbpf_type != type ||
1853
+ map -> sec_idx != sym -> st_shndx ||
1854
+ map -> sec_offset != sym -> st_value )
1855
+ continue ;
1856
+ pr_debug ("found map %zd (%s, sec %d, off %zu) for insn %u\n" ,
1857
+ map_idx , map -> name , map -> sec_idx ,
1858
+ map -> sec_offset , insn_idx );
1859
+ break ;
1860
+ }
1861
+ if (map_idx >= nr_maps ) {
1862
+ pr_warn ("map relo failed to find map for sec %u, off %llu\n" ,
1863
+ shdr_idx , (__u64 )sym -> st_value );
1864
+ return - LIBBPF_ERRNO__RELOC ;
1865
+ }
1866
+ reloc_desc -> type = RELO_LD64 ;
1867
+ reloc_desc -> insn_idx = insn_idx ;
1868
+ reloc_desc -> map_idx = map_idx ;
1869
+ return 0 ;
1870
+ }
1871
+
1872
+ /* global data map relocation */
1873
+ if (!bpf_object__shndx_is_data (obj , shdr_idx )) {
1874
+ pr_warn ("bad data relo against section %u\n" , shdr_idx );
1875
+ return - LIBBPF_ERRNO__RELOC ;
1876
+ }
1877
+ if (GELF_ST_BIND (sym -> st_info ) == STB_GLOBAL ) {
1878
+ pr_warn ("relocation: not yet supported relo for non-static global \'%s\' variable found in insns[%d].code 0x%x\n" ,
1879
+ name , insn_idx , insn -> code );
1880
+ return - LIBBPF_ERRNO__RELOC ;
1881
+ }
1882
+ if (!obj -> caps .global_data ) {
1883
+ pr_warn ("relocation: kernel does not support global \'%s\' variable access in insns[%d]\n" ,
1884
+ name , insn_idx );
1885
+ return - LIBBPF_ERRNO__RELOC ;
1886
+ }
1887
+ for (map_idx = 0 ; map_idx < nr_maps ; map_idx ++ ) {
1888
+ map = & obj -> maps [map_idx ];
1889
+ if (map -> libbpf_type != type )
1890
+ continue ;
1891
+ pr_debug ("found data map %zd (%s, sec %d, off %zu) for insn %u\n" ,
1892
+ map_idx , map -> name , map -> sec_idx , map -> sec_offset ,
1893
+ insn_idx );
1894
+ break ;
1895
+ }
1896
+ if (map_idx >= nr_maps ) {
1897
+ pr_warn ("data relo failed to find map for sec %u\n" ,
1898
+ shdr_idx );
1899
+ return - LIBBPF_ERRNO__RELOC ;
1900
+ }
1901
+
1902
+ reloc_desc -> type = RELO_DATA ;
1903
+ reloc_desc -> insn_idx = insn_idx ;
1904
+ reloc_desc -> map_idx = map_idx ;
1905
+ return 0 ;
1906
+ }
1907
+
1804
1908
static int
1805
1909
bpf_program__collect_reloc (struct bpf_program * prog , GElf_Shdr * shdr ,
1806
1910
Elf_Data * data , struct bpf_object * obj )
1807
1911
{
1808
1912
Elf_Data * symbols = obj -> efile .symbols ;
1809
- struct bpf_map * maps = obj -> maps ;
1810
- size_t nr_maps = obj -> nr_maps ;
1811
- int i , nrels ;
1913
+ int err , i , nrels ;
1812
1914
1813
1915
pr_debug ("collecting relocating info for: '%s'\n" , prog -> section_name );
1814
1916
nrels = shdr -> sh_size / shdr -> sh_entsize ;
@@ -1821,114 +1923,37 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
1821
1923
prog -> nr_reloc = nrels ;
1822
1924
1823
1925
for (i = 0 ; i < nrels ; i ++ ) {
1824
- struct bpf_insn * insns = prog -> insns ;
1825
- enum libbpf_map_type type ;
1826
- unsigned int insn_idx ;
1827
- unsigned int shdr_idx ;
1828
1926
const char * name ;
1829
- size_t map_idx ;
1927
+ __u32 insn_idx ;
1830
1928
GElf_Sym sym ;
1831
1929
GElf_Rel rel ;
1832
1930
1833
1931
if (!gelf_getrel (data , i , & rel )) {
1834
1932
pr_warn ("relocation: failed to get %d reloc\n" , i );
1835
1933
return - LIBBPF_ERRNO__FORMAT ;
1836
1934
}
1837
-
1838
1935
if (!gelf_getsym (symbols , GELF_R_SYM (rel .r_info ), & sym )) {
1839
1936
pr_warn ("relocation: symbol %" PRIx64 " not found\n" ,
1840
1937
GELF_R_SYM (rel .r_info ));
1841
1938
return - LIBBPF_ERRNO__FORMAT ;
1842
1939
}
1940
+ if (rel .r_offset % sizeof (struct bpf_insn ))
1941
+ return - LIBBPF_ERRNO__FORMAT ;
1843
1942
1943
+ insn_idx = rel .r_offset / sizeof (struct bpf_insn );
1844
1944
name = elf_strptr (obj -> efile .elf , obj -> efile .strtabidx ,
1845
1945
sym .st_name ) ? : "<?>" ;
1846
1946
1847
- pr_debug ("relo for %lld value %lld name %d (\'%s\')\n" ,
1848
- (long long ) (rel .r_info >> 32 ),
1849
- (long long ) sym .st_value , sym .st_name , name );
1850
-
1851
- shdr_idx = sym .st_shndx ;
1852
- insn_idx = rel .r_offset / sizeof (struct bpf_insn );
1853
- pr_debug ("relocation: insn_idx=%u, shdr_idx=%u\n" ,
1854
- insn_idx , shdr_idx );
1855
-
1856
- if (shdr_idx >= SHN_LORESERVE ) {
1857
- pr_warn ("relocation: not yet supported relo for non-static global \'%s\' variable in special section (0x%x) found in insns[%d].code 0x%x\n" ,
1858
- name , shdr_idx , insn_idx ,
1859
- insns [insn_idx ].code );
1860
- return - LIBBPF_ERRNO__RELOC ;
1861
- }
1862
- if (!bpf_object__relo_in_known_section (obj , shdr_idx )) {
1863
- pr_warn ("Program '%s' contains unrecognized relo data pointing to section %u\n" ,
1864
- prog -> section_name , shdr_idx );
1865
- return - LIBBPF_ERRNO__RELOC ;
1866
- }
1867
-
1868
- if (insns [insn_idx ].code == (BPF_JMP | BPF_CALL )) {
1869
- if (insns [insn_idx ].src_reg != BPF_PSEUDO_CALL ) {
1870
- pr_warn ("incorrect bpf_call opcode\n" );
1871
- return - LIBBPF_ERRNO__RELOC ;
1872
- }
1873
- if (sym .st_value % 8 ) {
1874
- pr_warn ("bad call relo offset: %lu\n" , sym .st_value );
1875
- return - LIBBPF_ERRNO__RELOC ;
1876
- }
1877
- prog -> reloc_desc [i ].type = RELO_CALL ;
1878
- prog -> reloc_desc [i ].insn_idx = insn_idx ;
1879
- prog -> reloc_desc [i ].text_off = sym .st_value / 8 ;
1880
- obj -> has_pseudo_calls = true;
1881
- continue ;
1882
- }
1883
-
1884
- if (insns [insn_idx ].code != (BPF_LD | BPF_IMM | BPF_DW )) {
1885
- pr_warn ("bpf: relocation: invalid relo for insns[%d].code 0x%x\n" ,
1886
- insn_idx , insns [insn_idx ].code );
1887
- return - LIBBPF_ERRNO__RELOC ;
1888
- }
1889
-
1890
- if (bpf_object__shndx_is_maps (obj , shdr_idx ) ||
1891
- bpf_object__shndx_is_data (obj , shdr_idx )) {
1892
- type = bpf_object__section_to_libbpf_map_type (obj , shdr_idx );
1893
- if (type != LIBBPF_MAP_UNSPEC ) {
1894
- if (GELF_ST_BIND (sym .st_info ) == STB_GLOBAL ) {
1895
- pr_warn ("bpf: relocation: not yet supported relo for non-static global \'%s\' variable found in insns[%d].code 0x%x\n" ,
1896
- name , insn_idx , insns [insn_idx ].code );
1897
- return - LIBBPF_ERRNO__RELOC ;
1898
- }
1899
- if (!obj -> caps .global_data ) {
1900
- pr_warn ("bpf: relocation: kernel does not support global \'%s\' variable access in insns[%d]\n" ,
1901
- name , insn_idx );
1902
- return - LIBBPF_ERRNO__RELOC ;
1903
- }
1904
- }
1905
-
1906
- for (map_idx = 0 ; map_idx < nr_maps ; map_idx ++ ) {
1907
- if (maps [map_idx ].libbpf_type != type )
1908
- continue ;
1909
- if (type != LIBBPF_MAP_UNSPEC ||
1910
- (maps [map_idx ].sec_idx == sym .st_shndx &&
1911
- maps [map_idx ].sec_offset == sym .st_value )) {
1912
- pr_debug ("relocation: found map %zd (%s, sec_idx %d, offset %zu) for insn %u\n" ,
1913
- map_idx , maps [map_idx ].name ,
1914
- maps [map_idx ].sec_idx ,
1915
- maps [map_idx ].sec_offset ,
1916
- insn_idx );
1917
- break ;
1918
- }
1919
- }
1920
-
1921
- if (map_idx >= nr_maps ) {
1922
- pr_warn ("bpf relocation: map_idx %d larger than %d\n" ,
1923
- (int )map_idx , (int )nr_maps - 1 );
1924
- return - LIBBPF_ERRNO__RELOC ;
1925
- }
1947
+ pr_debug ("relo for shdr %u, symb %llu, value %llu, type %d, bind %d, name %d (\'%s\'), insn %u\n" ,
1948
+ (__u32 )sym .st_shndx , (__u64 )GELF_R_SYM (rel .r_info ),
1949
+ (__u64 )sym .st_value , GELF_ST_TYPE (sym .st_info ),
1950
+ GELF_ST_BIND (sym .st_info ), sym .st_name , name ,
1951
+ insn_idx );
1926
1952
1927
- prog -> reloc_desc [i ].type = type != LIBBPF_MAP_UNSPEC ?
1928
- RELO_DATA : RELO_LD64 ;
1929
- prog -> reloc_desc [i ].insn_idx = insn_idx ;
1930
- prog -> reloc_desc [i ].map_idx = map_idx ;
1931
- }
1953
+ err = bpf_program__record_reloc (prog , & prog -> reloc_desc [i ],
1954
+ insn_idx , name , & sym , & rel );
1955
+ if (err )
1956
+ return err ;
1932
1957
}
1933
1958
return 0 ;
1934
1959
}
@@ -3671,9 +3696,9 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
3671
3696
return - LIBBPF_ERRNO__INTERNAL ;
3672
3697
}
3673
3698
3674
- for (i = 0 ; i < obj -> efile .nr_reloc ; i ++ ) {
3675
- GElf_Shdr * shdr = & obj -> efile .reloc [i ].shdr ;
3676
- Elf_Data * data = obj -> efile .reloc [i ].data ;
3699
+ for (i = 0 ; i < obj -> efile .nr_reloc_sects ; i ++ ) {
3700
+ GElf_Shdr * shdr = & obj -> efile .reloc_sects [i ].shdr ;
3701
+ Elf_Data * data = obj -> efile .reloc_sects [i ].data ;
3677
3702
int idx = shdr -> sh_info ;
3678
3703
struct bpf_program * prog ;
3679
3704
0 commit comments